diff --git a/metadata-operation-context/build.gradle b/metadata-operation-context/build.gradle index 1be98cb0140f3..650082ef0d25e 100644 --- a/metadata-operation-context/build.gradle +++ b/metadata-operation-context/build.gradle @@ -7,6 +7,8 @@ dependencies { api project(':metadata-auth:auth-api') implementation externalDependency.slf4jApi + implementation externalDependency.servletApi + implementation spec.product.pegasus.restliServer compileOnly externalDependency.lombok annotationProcessor externalDependency.lombok diff --git a/metadata-operation-context/src/main/java/io/datahubproject/metadata/context/RequestContext.java b/metadata-operation-context/src/main/java/io/datahubproject/metadata/context/RequestContext.java index 83090b9235701..dcea185fcbc7c 100644 --- a/metadata-operation-context/src/main/java/io/datahubproject/metadata/context/RequestContext.java +++ b/metadata-operation-context/src/main/java/io/datahubproject/metadata/context/RequestContext.java @@ -1,5 +1,8 @@ package io.datahubproject.metadata.context; +import com.google.common.net.HttpHeaders; +import com.linkedin.restli.server.ResourceContext; +import jakarta.servlet.http.HttpServletRequest; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -11,7 +14,9 @@ import javax.annotation.Nullable; import lombok.Builder; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +@Slf4j @Getter @Builder public class RequestContext implements ContextInterface { @@ -19,6 +24,8 @@ public class RequestContext implements ContextInterface { public static final RequestContext TEST = RequestContext.builder().requestID("test").requestAPI(RequestAPI.TEST).build(); + @Nonnull private final String actorUrn; + @Nonnull private final String sourceIP; @Nonnull private final RequestAPI requestAPI; /** @@ -27,6 +34,23 @@ public class RequestContext implements ContextInterface { */ @Nonnull private final String requestID; + @Nonnull private final String userAgent; + + public RequestContext( + @Nonnull String actorUrn, + @Nonnull String sourceIP, + @Nonnull RequestAPI requestAPI, + @Nonnull String requestID, + @Nonnull String userAgent) { + this.actorUrn = actorUrn; + this.sourceIP = sourceIP; + this.requestAPI = requestAPI; + this.requestID = requestID; + this.userAgent = userAgent; + // Uniform common logging of requests across APIs + log.info(toString()); + } + @Override public Optional getCacheKeyComponent() { return Optional.empty(); @@ -34,39 +58,76 @@ public Optional getCacheKeyComponent() { public static class RequestContextBuilder { private RequestContext build() { - return new RequestContext(this.requestAPI, this.requestID); + return new RequestContext( + this.actorUrn, this.sourceIP, this.requestAPI, this.requestID, this.userAgent); } - public RequestContext buildGraphql(@Nonnull String queryName, Map variables) { + public RequestContext buildGraphql( + @Nonnull String actorUrn, + @Nonnull HttpServletRequest request, + @Nonnull String queryName, + Map variables) { + actorUrn(actorUrn); + sourceIP(extractSourceIP(request)); requestAPI(RequestAPI.GRAPHQL); requestID(buildRequestId(queryName, Set.of())); + userAgent(extractUserAgent(request)); return build(); } - public RequestContext buildRestli(String action, @Nullable String entityName) { - return buildRestli(action, entityName == null ? null : List.of(entityName)); + public RequestContext buildRestli( + @Nonnull String actorUrn, + @Nullable ResourceContext resourceContext, + String action, + @Nullable String entityName) { + return buildRestli( + actorUrn, resourceContext, action, entityName == null ? null : List.of(entityName)); } - public RequestContext buildRestli(@Nonnull String action, @Nullable String[] entityNames) { + public RequestContext buildRestli( + @Nonnull String actorUrn, + @Nullable ResourceContext resourceContext, + @Nonnull String action, + @Nullable String[] entityNames) { return buildRestli( + actorUrn, + resourceContext, action, entityNames == null ? null : Arrays.stream(entityNames).collect(Collectors.toList())); } - public RequestContext buildRestli(String action, @Nullable Collection entityNames) { + public RequestContext buildRestli( + @Nonnull String actorUrn, + @Nullable ResourceContext resourceContext, + String action, + @Nullable Collection entityNames) { + actorUrn(actorUrn); + sourceIP(resourceContext == null ? "" : extractSourceIP(resourceContext)); requestAPI(RequestAPI.RESTLI); requestID(buildRequestId(action, entityNames)); + userAgent(resourceContext == null ? "" : extractUserAgent(resourceContext)); return build(); } - public RequestContext buildOpenapi(@Nonnull String action, @Nullable String entityName) { - return buildOpenapi(action, entityName == null ? null : List.of(entityName)); + public RequestContext buildOpenapi( + @Nonnull String actorUrn, + @Nonnull HttpServletRequest request, + @Nonnull String action, + @Nullable String entityName) { + return buildOpenapi( + actorUrn, request, action, entityName == null ? null : List.of(entityName)); } public RequestContext buildOpenapi( - @Nonnull String action, @Nullable Collection entityNames) { + @Nonnull String actorUrn, + @Nullable HttpServletRequest request, + @Nonnull String action, + @Nullable Collection entityNames) { + actorUrn(actorUrn); + sourceIP(request == null ? "" : extractSourceIP(request)); requestAPI(RequestAPI.OPENAPI); requestID(buildRequestId(action, entityNames)); + userAgent(request == null ? "" : extractUserAgent(request)); return build(); } @@ -77,6 +138,46 @@ private static String buildRequestId( : String.format( "%s(%s)", action, entityNames.stream().distinct().collect(Collectors.toList())); } + + private static String extractUserAgent(@Nonnull HttpServletRequest request) { + return Optional.ofNullable(request.getHeader(HttpHeaders.USER_AGENT)).orElse(""); + } + + private static String extractUserAgent(@Nonnull ResourceContext resourceContext) { + return Optional.ofNullable(resourceContext.getRequestHeaders().get(HttpHeaders.USER_AGENT)) + .orElse(""); + } + + private static String extractSourceIP(@Nonnull HttpServletRequest request) { + return Optional.ofNullable(request.getHeader(HttpHeaders.X_FORWARDED_FOR)) + .orElse(request.getRemoteAddr()); + } + + private static String extractSourceIP(@Nonnull ResourceContext resourceContext) { + return Optional.ofNullable( + resourceContext.getRequestHeaders().get(HttpHeaders.X_FORWARDED_FOR)) + .orElse(resourceContext.getRawRequestContext().getLocalAttr("REMOTE_ADDR").toString()); + } + } + + @Override + public String toString() { + return "RequestContext{" + + "actorUrn='" + + actorUrn + + '\'' + + ", sourceIP='" + + sourceIP + + '\'' + + ", requestAPI=" + + requestAPI + + ", requestID='" + + requestID + + '\'' + + ", userAgent='" + + userAgent + + '\'' + + '}'; } public enum RequestAPI { diff --git a/metadata-service/graphql-servlet-impl/src/main/java/com/datahub/graphql/GraphQLController.java b/metadata-service/graphql-servlet-impl/src/main/java/com/datahub/graphql/GraphQLController.java index af69dce89041e..2f383b1956313 100644 --- a/metadata-service/graphql-servlet-impl/src/main/java/com/datahub/graphql/GraphQLController.java +++ b/metadata-service/graphql-servlet-impl/src/main/java/com/datahub/graphql/GraphQLController.java @@ -59,7 +59,8 @@ public GraphQLController() { private static final int MAX_LOG_WIDTH = 512; @PostMapping(value = "/graphql", produces = "application/json;charset=utf-8") - CompletableFuture> postGraphQL(HttpEntity httpEntity) { + CompletableFuture> postGraphQL( + HttpServletRequest request, HttpEntity httpEntity) { String jsonStr = httpEntity.getBody(); ObjectMapper mapper = new ObjectMapper(); @@ -117,13 +118,18 @@ CompletableFuture> postGraphQL(HttpEntity httpEnt SpringQueryContext context = new SpringQueryContext( - true, authentication, _authorizerChain, systemOperationContext, query, variables); + true, + authentication, + _authorizerChain, + systemOperationContext, + request, + operationName, + query, + variables); Span.current().setAttribute("actor.urn", context.getActorUrn()); - // operationName is an optional field only required if multiple operations are present - final String queryName = operationName != null ? operationName : context.getQueryName(); final String threadName = Thread.currentThread().getName(); - log.info("Processing request, operation: {}, actor urn: {}", queryName, context.getActorUrn()); + final String queryName = context.getQueryName(); log.debug("Query: {}, variables: {}", query, variables); return GraphQLConcurrencyUtils.supplyAsync( diff --git a/metadata-service/graphql-servlet-impl/src/main/java/com/datahub/graphql/SpringQueryContext.java b/metadata-service/graphql-servlet-impl/src/main/java/com/datahub/graphql/SpringQueryContext.java index 591e1158879d4..8aa22efb785e2 100644 --- a/metadata-service/graphql-servlet-impl/src/main/java/com/datahub/graphql/SpringQueryContext.java +++ b/metadata-service/graphql-servlet-impl/src/main/java/com/datahub/graphql/SpringQueryContext.java @@ -7,8 +7,10 @@ import graphql.parser.Parser; import io.datahubproject.metadata.context.OperationContext; import io.datahubproject.metadata.context.RequestContext; +import jakarta.servlet.http.HttpServletRequest; import java.util.Map; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import lombok.Getter; @Getter @@ -25,26 +27,33 @@ public SpringQueryContext( final Authentication authentication, final Authorizer authorizer, @Nonnull final OperationContext systemOperationContext, + @Nonnull final HttpServletRequest request, + @Nullable final String operationName, String jsonQuery, Map variables) { this.isAuthenticated = isAuthenticated; this.authentication = authentication; this.authorizer = authorizer; + // operationName is an optional field only required if multiple operations are present this.queryName = - new Parser() - .parseDocument(jsonQuery).getDefinitions().stream() - .filter(def -> def instanceof OperationDefinition) - .map(def -> (OperationDefinition) def) - .filter(opDef -> opDef.getOperation().equals(OperationDefinition.Operation.QUERY)) - .findFirst() - .map(OperationDefinition::getName) - .orElse("graphql"); + operationName != null + ? operationName + : new Parser() + .parseDocument(jsonQuery).getDefinitions().stream() + .filter(def -> def instanceof OperationDefinition) + .map(def -> (OperationDefinition) def) + .filter( + opDef -> opDef.getOperation().equals(OperationDefinition.Operation.QUERY)) + .findFirst() + .map(OperationDefinition::getName) + .orElse("graphql"); this.operationContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildGraphql(queryName, variables), + RequestContext.builder() + .buildGraphql(authentication.getActor().toUrnStr(), request, queryName, variables), authorizer, authentication, true); diff --git a/metadata-service/openapi-analytics-servlet/build.gradle b/metadata-service/openapi-analytics-servlet/build.gradle index 3a879cb1b0071..5d1372a293775 100644 --- a/metadata-service/openapi-analytics-servlet/build.gradle +++ b/metadata-service/openapi-analytics-servlet/build.gradle @@ -19,7 +19,7 @@ dependencies { implementation externalDependency.springWebMVC implementation externalDependency.springBeans implementation externalDependency.springContext - + implementation externalDependency.servletApi implementation externalDependency.reflections implementation externalDependency.slf4jApi compileOnly externalDependency.lombok diff --git a/metadata-service/openapi-analytics-servlet/src/main/java/io/datahubproject/openapi/delegates/DatahubUsageEventsImpl.java b/metadata-service/openapi-analytics-servlet/src/main/java/io/datahubproject/openapi/delegates/DatahubUsageEventsImpl.java index 53df1e50ffbca..dc6d4a33f936e 100644 --- a/metadata-service/openapi-analytics-servlet/src/main/java/io/datahubproject/openapi/delegates/DatahubUsageEventsImpl.java +++ b/metadata-service/openapi-analytics-servlet/src/main/java/io/datahubproject/openapi/delegates/DatahubUsageEventsImpl.java @@ -12,6 +12,7 @@ import io.datahubproject.metadata.context.RequestContext; import io.datahubproject.openapi.exception.UnauthorizedException; import io.datahubproject.openapi.v2.generated.controller.DatahubUsageEventsApiDelegate; +import jakarta.servlet.http.HttpServletRequest; import java.util.List; import java.util.Objects; import org.springframework.beans.factory.annotation.Autowired; @@ -27,6 +28,8 @@ public class DatahubUsageEventsImpl implements DatahubUsageEventsApiDelegate { @Qualifier("systemOperationContext") OperationContext systemOperationContext; + @Autowired private HttpServletRequest request; + public static final String DATAHUB_USAGE_INDEX = "datahub_usage_event"; @Override @@ -36,7 +39,8 @@ public ResponseEntity raw(String body) { OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("raw", List.of()), + RequestContext.builder() + .buildOpenapi(authentication.getActor().toUrnStr(), request, "raw", List.of()), _authorizationChain, authentication, true); diff --git a/metadata-service/openapi-entity-servlet/src/main/java/io/datahubproject/openapi/v2/delegates/EntityApiDelegateImpl.java b/metadata-service/openapi-entity-servlet/src/main/java/io/datahubproject/openapi/v2/delegates/EntityApiDelegateImpl.java index bd4d68834b9e8..12caba3e39dd6 100644 --- a/metadata-service/openapi-entity-servlet/src/main/java/io/datahubproject/openapi/v2/delegates/EntityApiDelegateImpl.java +++ b/metadata-service/openapi-entity-servlet/src/main/java/io/datahubproject/openapi/v2/delegates/EntityApiDelegateImpl.java @@ -59,6 +59,7 @@ import io.datahubproject.openapi.generated.StatusAspectResponseV2; import io.datahubproject.openapi.util.OpenApiEntitiesUtil; import io.datahubproject.openapi.v1.entities.EntitiesController; +import jakarta.servlet.http.HttpServletRequest; import java.net.URISyntaxException; import java.util.List; import java.util.Map; @@ -85,6 +86,7 @@ public class EntityApiDelegateImpl { private final Class _reqClazz; private final Class _respClazz; private final Class _scrollRespClazz; + private final HttpServletRequest request; private static final String BUSINESS_ATTRIBUTE_ERROR_MESSAGE = "business attribute is disabled, enable it using featureflag : BUSINESS_ATTRIBUTE_ENTITY_ENABLED"; @@ -92,6 +94,7 @@ public class EntityApiDelegateImpl { public EntityApiDelegateImpl( OperationContext systemOperationContext, + HttpServletRequest request, EntityService entityService, SearchService searchService, EntitiesController entitiesController, @@ -100,6 +103,7 @@ public EntityApiDelegateImpl( Class respClazz, Class scrollRespClazz) { this.systemOperationContext = systemOperationContext; + this.request = request; this._entityService = entityService; this._searchService = searchService; this._entityRegistry = systemOperationContext.getEntityRegistry(); @@ -119,7 +123,7 @@ public ResponseEntity get(String urn, Boolean systemMetadata, List as .map(asp -> asp.stream().distinct().toArray(String[]::new)) .orElse(null); ResponseEntity result = - _v1Controller.getEntities(new String[] {urn}, requestedAspects); + _v1Controller.getEntities(request, new String[] {urn}, requestedAspects); return ResponseEntity.of( OpenApiEntitiesUtil.convertEntity( Optional.ofNullable(result).map(HttpEntity::getBody).orElse(null), @@ -146,7 +150,7 @@ public ResponseEntity> create( throw new UnsupportedOperationException(BUSINESS_ATTRIBUTE_ERROR_MESSAGE); } } - _v1Controller.postEntities(aspects, false, createIfNotExists, createEntityIfNotExists); + _v1Controller.postEntities(request, aspects, false, createIfNotExists, createEntityIfNotExists); List responses = body.stream() .map(req -> OpenApiEntitiesUtil.convertToResponse(req, _respClazz, _entityRegistry)) @@ -158,7 +162,7 @@ public ResponseEntity delete(String urn) { if (checkBusinessAttributeFlagFromUrn(urn)) { throw new UnsupportedOperationException(BUSINESS_ATTRIBUTE_ERROR_MESSAGE); } - _v1Controller.deleteEntities(new String[] {urn}, false, false); + _v1Controller.deleteEntities(request, new String[] {urn}, false, false); return new ResponseEntity<>(HttpStatus.OK); } @@ -177,7 +181,9 @@ public ResponseEntity head(String urn) { OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("head", entityUrn.getEntityType()), + RequestContext.builder() + .buildOpenapi( + auth.getActor().toUrnStr(), request, "head", entityUrn.getEntityType()), _authorizationChain, auth, true); @@ -200,7 +206,7 @@ public ResponseEntity getAspect( Class aspectRespClazz) { String[] requestedAspects = new String[] {aspect}; ResponseEntity result = - _v1Controller.getEntities(new String[] {urn}, requestedAspects); + _v1Controller.getEntities(request, new String[] {urn}, requestedAspects); return ResponseEntity.of( OpenApiEntitiesUtil.convertAspect( result.getBody(), aspect, entityRespClass, aspectRespClazz, systemMetadata)); @@ -217,6 +223,7 @@ public ResponseEntity createAspect( UpsertAspectRequest aspectUpsert = OpenApiEntitiesUtil.convertAspectToUpsert(urn, body, reqClazz); _v1Controller.postEntities( + request, Stream.of(aspectUpsert).filter(Objects::nonNull).collect(Collectors.toList()), false, createIfNotExists, @@ -238,7 +245,9 @@ public ResponseEntity headAspect(String urn, String aspect) { OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("headAspect", entityUrn.getEntityType()), + RequestContext.builder() + .buildOpenapi( + auth.getActor().toUrnStr(), request, "headAspect", entityUrn.getEntityType()), _authorizationChain, auth, true); @@ -259,12 +268,14 @@ public ResponseEntity deleteAspect(String urn, String aspect) { OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("deleteAspect", entityUrn.getEntityType()), + RequestContext.builder() + .buildOpenapi( + auth.getActor().toUrnStr(), request, "deleteAspect", entityUrn.getEntityType()), _authorizationChain, auth, true); _entityService.deleteAspect(opContext, urn, aspect, Map.of(), false); - _v1Controller.deleteEntities(new String[] {urn}, false, false); + _v1Controller.deleteEntities(request, new String[] {urn}, false, false); return new ResponseEntity<>(HttpStatus.OK); } @@ -606,7 +617,9 @@ public ResponseEntity scroll( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("scroll", entitySpec.getName()), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "scroll", entitySpec.getName()), _authorizationChain, authentication, true); @@ -644,7 +657,7 @@ public ResponseEntity scroll( .map(asp -> asp.stream().distinct().toArray(String[]::new)) .orElse(null); List entities = - Optional.ofNullable(_v1Controller.getEntities(urns, requestedAspects).getBody()) + Optional.ofNullable(_v1Controller.getEntities(request, urns, requestedAspects).getBody()) .map(body -> body.getResponses().entrySet()) .map( entries -> OpenApiEntitiesUtil.convertEntities(entries, _respClazz, systemMetadata)) diff --git a/metadata-service/openapi-entity-servlet/src/main/resources/JavaSpring/apiController.mustache b/metadata-service/openapi-entity-servlet/src/main/resources/JavaSpring/apiController.mustache index 04bc7e52c593b..fbf354ff91688 100644 --- a/metadata-service/openapi-entity-servlet/src/main/resources/JavaSpring/apiController.mustache +++ b/metadata-service/openapi-entity-servlet/src/main/resources/JavaSpring/apiController.mustache @@ -98,7 +98,7 @@ public class {{classname}}Controller implements {{classname}} { SearchService searchService, EntitiesController v1Controller, AuthorizerChain authorizationChain) { this.objectMapper = objectMapper; this.request = request; - this.delegate = new EntityApiDelegateImpl<{{requestClass}}, {{responseClass}}, {{scrollResponseClass}}>(systemOperationContext, entityService, searchService, v1Controller, + this.delegate = new EntityApiDelegateImpl<{{requestClass}}, {{responseClass}}, {{scrollResponseClass}}>(systemOperationContext, request, entityService, searchService, v1Controller, authorizationChain, {{requestClass}}.class, {{responseClass}}.class, {{scrollResponseClass}}.class); } {{#isJava8or11}} diff --git a/metadata-service/openapi-entity-servlet/src/test/java/io/datahubproject/openapi/config/OpenAPIEntityTestConfiguration.java b/metadata-service/openapi-entity-servlet/src/test/java/io/datahubproject/openapi/config/OpenAPIEntityTestConfiguration.java index c1398e8616747..075501c1a1071 100644 --- a/metadata-service/openapi-entity-servlet/src/test/java/io/datahubproject/openapi/config/OpenAPIEntityTestConfiguration.java +++ b/metadata-service/openapi-entity-servlet/src/test/java/io/datahubproject/openapi/config/OpenAPIEntityTestConfiguration.java @@ -3,6 +3,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -33,6 +34,7 @@ import io.datahubproject.openapi.v1.relationships.RelationshipsController; import io.datahubproject.openapi.v2.controller.TimelineControllerV2; import io.datahubproject.test.metadata.context.TestOperationContexts; +import jakarta.servlet.http.HttpServletRequest; import java.util.Arrays; import java.util.Map; import java.util.stream.Collectors; @@ -109,11 +111,11 @@ public EntityRegistry entityRegistry() throws EntityRegistryException, Interrupt @Primary public EntitiesController entitiesController() { EntitiesController entitiesController = mock(EntitiesController.class); - when(entitiesController.getEntities(any(), any())) + when(entitiesController.getEntities(nullable(HttpServletRequest.class), any(), any())) .thenAnswer( params -> { - String[] urns = params.getArgument(0); - String[] aspects = params.getArgument(1); + String[] urns = params.getArgument(1); + String[] aspects = params.getArgument(2); return ResponseEntity.ok( UrnResponseMap.builder() .responses( diff --git a/metadata-service/openapi-servlet/build.gradle b/metadata-service/openapi-servlet/build.gradle index 7b6a3c7c89e31..e26b1ceea1a3c 100644 --- a/metadata-service/openapi-servlet/build.gradle +++ b/metadata-service/openapi-servlet/build.gradle @@ -21,6 +21,7 @@ dependencies { implementation externalDependency.springWebMVC implementation externalDependency.springBeans implementation externalDependency.springContext + implementation externalDependency.servletApi implementation externalDependency.slf4jApi compileOnly externalDependency.lombok implementation externalDependency.antlr4Runtime diff --git a/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/controller/GenericEntitiesController.java b/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/controller/GenericEntitiesController.java index 6869f7bf58235..30988d81db2f9 100644 --- a/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/controller/GenericEntitiesController.java +++ b/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/controller/GenericEntitiesController.java @@ -52,6 +52,7 @@ import io.datahubproject.openapi.models.GenericEntityScrollResult; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import java.lang.reflect.InvocationTargetException; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; @@ -133,6 +134,7 @@ protected abstract AspectsBatch toMCPBatch( @GetMapping(value = "/{entityName}", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Scroll entities") public ResponseEntity getEntities( + HttpServletRequest request, @PathVariable("entityName") String entityName, @RequestParam(value = "aspectNames", defaultValue = "") Set aspects1, @RequestParam(value = "aspects", defaultValue = "") Set aspects2, @@ -159,7 +161,9 @@ public ResponseEntity getEntities( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("getEntities", entityName), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "getEntities", entityName), authorizationChain, authentication, true); @@ -199,6 +203,7 @@ public ResponseEntity getEntities( value = "/{entityName}/{entityUrn:urn:li:.+}", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity getEntity( + HttpServletRequest request, @PathVariable("entityName") String entityName, @PathVariable("entityUrn") String entityUrn, @RequestParam(value = "aspectNames", defaultValue = "") Set aspects1, @@ -217,7 +222,9 @@ public ResponseEntity getEntity( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("getEntity", entityName), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "getEntity", entityName), authorizationChain, authentication, true); @@ -239,6 +246,7 @@ public ResponseEntity getEntity( method = {RequestMethod.HEAD}) @Operation(summary = "Entity exists") public ResponseEntity headEntity( + HttpServletRequest request, @PathVariable("entityName") String entityName, @PathVariable("entityUrn") String entityUrn, @PathVariable(value = "includeSoftDelete", required = false) Boolean includeSoftDelete) @@ -254,7 +262,9 @@ public ResponseEntity headEntity( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("headEntity", entityName), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "headEntity", entityName), authorizationChain, authentication, true); @@ -270,6 +280,7 @@ public ResponseEntity headEntity( produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Get an entity's generic aspect.") public ResponseEntity getAspect( + HttpServletRequest request, @PathVariable("entityName") String entityName, @PathVariable("entityUrn") String entityUrn, @PathVariable("aspectName") String aspectName, @@ -287,7 +298,9 @@ public ResponseEntity getAspect( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("getAspect", entityName), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "getAspect", entityName), authorizationChain, authentication, true); @@ -311,6 +324,7 @@ public ResponseEntity getAspect( method = {RequestMethod.HEAD}) @Operation(summary = "Whether an entity aspect exists.") public ResponseEntity headAspect( + HttpServletRequest request, @PathVariable("entityName") String entityName, @PathVariable("entityUrn") String entityUrn, @PathVariable("aspectName") String aspectName, @@ -327,7 +341,9 @@ public ResponseEntity headAspect( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("headAspect", entityName), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "headAspect", entityName), authorizationChain, authentication, true); @@ -341,7 +357,9 @@ public ResponseEntity headAspect( @DeleteMapping(value = "/{entityName}/{entityUrn:urn:li:.+}") @Operation(summary = "Delete an entity") public void deleteEntity( - @PathVariable("entityName") String entityName, @PathVariable("entityUrn") String entityUrn) + HttpServletRequest request, + @PathVariable("entityName") String entityName, + @PathVariable("entityUrn") String entityUrn) throws InvalidUrnException { EntitySpec entitySpec = entityRegistry.getEntitySpec(entityName); @@ -355,7 +373,9 @@ public void deleteEntity( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("deleteEntity", entityName), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "deleteEntity", entityName), authorizationChain, authentication, true); @@ -367,6 +387,7 @@ public void deleteEntity( @PostMapping(value = "/{entityName}", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Create a batch of entities.") public ResponseEntity> createEntity( + HttpServletRequest request, @PathVariable("entityName") String entityName, @RequestParam(value = "async", required = false, defaultValue = "true") Boolean async, @RequestParam(value = "systemMetadata", required = false, defaultValue = "false") @@ -385,7 +406,9 @@ public ResponseEntity> createEntity( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("createEntity", entityName), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "createEntity", entityName), authorizationChain, authentication, true); @@ -404,6 +427,7 @@ public ResponseEntity> createEntity( @DeleteMapping(value = "/{entityName}/{entityUrn:urn:li:.+}/{aspectName}") @Operation(summary = "Delete an entity aspect.") public void deleteAspect( + HttpServletRequest request, @PathVariable("entityName") String entityName, @PathVariable("entityUrn") String entityUrn, @PathVariable("aspectName") String aspectName) @@ -419,7 +443,9 @@ public void deleteAspect( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("deleteAspect", entityName), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "deleteAspect", entityName), authorizationChain, authentication, true); @@ -434,6 +460,7 @@ public void deleteAspect( produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Create an entity aspect.") public ResponseEntity createAspect( + HttpServletRequest request, @PathVariable("entityName") String entityName, @PathVariable("entityUrn") String entityUrn, @PathVariable("aspectName") String aspectName, @@ -456,7 +483,9 @@ public ResponseEntity createAspect( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("createAspect", entityName), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "createAspect", entityName), authorizationChain, authentication, true); @@ -494,6 +523,7 @@ public ResponseEntity createAspect( produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Patch an entity aspect. (Experimental)") public ResponseEntity patchAspect( + HttpServletRequest request, @PathVariable("entityName") String entityName, @PathVariable("entityUrn") String entityUrn, @PathVariable("aspectName") String aspectName, @@ -517,7 +547,9 @@ public ResponseEntity patchAspect( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("patchAspect", entityName), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "patchAspect", entityName), authorizationChain, authentication, true); diff --git a/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/openlineage/controller/LineageApiImpl.java b/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/openlineage/controller/LineageApiImpl.java index f483d6ded1f10..f1da20fefe6bf 100644 --- a/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/openlineage/controller/LineageApiImpl.java +++ b/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/openlineage/controller/LineageApiImpl.java @@ -14,6 +14,7 @@ import io.datahubproject.openlineage.generated.controller.LineageApi; import io.openlineage.client.OpenLineage; import io.openlineage.client.OpenLineageClientUtils; +import jakarta.servlet.http.HttpServletRequest; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -50,6 +51,8 @@ public Optional getObjectMapper() { return Optional.of(OBJECT_MAPPER); } + @Autowired private HttpServletRequest request; + @Override public ResponseEntity postRunEventRaw(String body) { try { @@ -68,7 +71,9 @@ public ResponseEntity postRunEventRaw(OpenLineage.RunEvent openlineageRunE OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("postRunEventRaw", List.of()), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "postRunEventRaw", List.of()), _authorizerChain, authentication, true); diff --git a/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/operations/elastic/OperationsController.java b/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/operations/elastic/OperationsController.java index 341f2a45197d1..ddbc8004081eb 100644 --- a/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/operations/elastic/OperationsController.java +++ b/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/operations/elastic/OperationsController.java @@ -31,6 +31,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import java.net.URISyntaxException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; @@ -133,7 +134,7 @@ public ResponseEntity getTaskStatus(String task) { @Tag(name = "ElasticSearchOperations") @GetMapping(path = "/getIndexSizes", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Get Index Sizes") - public ResponseEntity getIndexSizes() { + public ResponseEntity getIndexSizes(HttpServletRequest request) { Authentication authentication = AuthenticationContext.getAuthentication(); String actorUrnStr = authentication.getActor().toUrnStr(); @@ -145,7 +146,7 @@ public ResponseEntity getIndexSizes() { OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("getIndexSizes", List.of()), + RequestContext.builder().buildOpenapi(actorUrnStr, request, "getIndexSizes", List.of()), authorizerChain, authentication, true); @@ -171,6 +172,7 @@ public ResponseEntity getIndexSizes() { @GetMapping(path = "/explainSearchQuery", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Explain Search Query") public ResponseEntity explainSearchQuery( + HttpServletRequest request, @Parameter( name = "query", required = true, @@ -229,7 +231,8 @@ public ResponseEntity explainSearchQuery( OperationContext opContext = systemOperationContext .asSession( - RequestContext.builder().buildOpenapi("explainSearchQuery", entityName), + RequestContext.builder() + .buildOpenapi(actorUrnStr, request, "explainSearchQuery", entityName), authorizerChain, authentication) .withSearchFlags( @@ -263,6 +266,7 @@ public ResponseEntity explainSearchQuery( @GetMapping(path = "/explainSearchQueryDiff", produces = MediaType.TEXT_PLAIN_VALUE) @Operation(summary = "Explain the differences in scoring for 2 documents") public ResponseEntity explainSearchQueryDiff( + HttpServletRequest request, @Parameter( name = "query", required = true, @@ -328,7 +332,8 @@ public ResponseEntity explainSearchQueryDiff( OperationContext opContext = systemOperationContext .asSession( - RequestContext.builder().buildOpenapi("explainSearchQuery", entityName), + RequestContext.builder() + .buildOpenapi(actorUrnStr, request, "explainSearchQuery", entityName), authorizerChain, authentication) .withSearchFlags( @@ -400,6 +405,7 @@ private static String encodeValue(String value) { @GetMapping(path = "/restoreIndices", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Restore ElasticSearch indices from primary storage based on URNs.") public ResponseEntity> restoreIndices( + HttpServletRequest request, @RequestParam(required = false, name = "aspectName") @Nullable String aspectName, @RequestParam(required = false, name = "urn") @Nullable String urn, @RequestParam(required = false, name = "urnLike") @Nullable String urnLike, @@ -419,7 +425,9 @@ public ResponseEntity> restoreIndices( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("restoreIndices", List.of()), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "restoreIndices", List.of()), authorizerChain, authentication, true); @@ -445,6 +453,7 @@ public ResponseEntity> restoreIndices( @PostMapping(path = "/restoreIndices", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Restore ElasticSearch indices from primary storage based on URNs.") public ResponseEntity> restoreIndices( + HttpServletRequest request, @RequestParam(required = false, name = "aspectNames") @Nullable Set aspectNames, @RequestParam(required = false, name = "batchSize", defaultValue = "100") @Nullable Integer batchSize, @@ -459,7 +468,9 @@ public ResponseEntity> restoreIndices( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("restoreIndices", List.of()), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "restoreIndices", List.of()), authorizerChain, authentication, true); diff --git a/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v1/entities/EntitiesController.java b/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v1/entities/EntitiesController.java index 8632cedbf8ffb..99eede15629d2 100644 --- a/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v1/entities/EntitiesController.java +++ b/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v1/entities/EntitiesController.java @@ -30,6 +30,7 @@ import io.datahubproject.openapi.util.MappingUtil; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import java.net.URLDecoder; import java.util.Arrays; import java.util.Collections; @@ -90,6 +91,7 @@ public void initBinder(WebDataBinder binder) { @GetMapping(value = "/latest", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity getEntities( + HttpServletRequest request, @Parameter( name = "urns", required = true, @@ -122,6 +124,8 @@ public ResponseEntity getEntities( systemOperationContext, RequestContext.builder() .buildOpenapi( + actorUrnStr, + request, "getEntities", entityUrns.stream() .map(Urn::getEntityType) @@ -169,6 +173,7 @@ public ResponseEntity getEntities( @PostMapping(value = "/", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity> postEntities( + HttpServletRequest request, @RequestBody @Nonnull List aspectRequests, @RequestParam(required = false, name = "async") Boolean async, @RequestParam(required = false, name = "createIfNotExists") Boolean createIfNotExists, @@ -191,6 +196,8 @@ public ResponseEntity> postEntities( systemOperationContext, RequestContext.builder() .buildOpenapi( + actorUrnStr, + request, "postEntities", proposals.stream() .map(MetadataChangeProposal::getEntityType) @@ -241,6 +248,7 @@ public ResponseEntity> postEntities( @DeleteMapping(value = "/", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity> deleteEntities( + HttpServletRequest request, @Parameter( name = "urns", required = true, @@ -278,6 +286,8 @@ public ResponseEntity> deleteEntities( systemOperationContext, RequestContext.builder() .buildOpenapi( + actorUrnStr, + request, "deleteEntities", entityUrns.stream().map(Urn::getEntityType).collect(Collectors.toSet())), _authorizerChain, diff --git a/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v2/controller/EntityController.java b/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v2/controller/EntityController.java index eeba41f9f819f..b40aba2d2908f 100644 --- a/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v2/controller/EntityController.java +++ b/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v2/controller/EntityController.java @@ -38,6 +38,7 @@ import io.datahubproject.openapi.v2.models.GenericEntityV2; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -87,7 +88,9 @@ public GenericEntityScrollResultV2 buildScrollResult( @PostMapping(value = "/batch/{entityName}", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Get a batch of entities") public ResponseEntity getEntityBatch( - @PathVariable("entityName") String entityName, @RequestBody BatchGetUrnRequest request) + HttpServletRequest httpServletRequest, + @PathVariable("entityName") String entityName, + @RequestBody BatchGetUrnRequest request) throws URISyntaxException { List urns = request.getUrns().stream().map(UrnUtils::getUrn).collect(Collectors.toList()); @@ -100,7 +103,12 @@ public ResponseEntity getEntityBatch( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("getEntityBatch", entityName), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), + httpServletRequest, + "getEntityBatch", + entityName), authorizationChain, authentication, true); diff --git a/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v2/controller/PlatformEntitiesController.java b/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v2/controller/PlatformEntitiesController.java index 1d0de44c0d83a..87c72064ad7a7 100644 --- a/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v2/controller/PlatformEntitiesController.java +++ b/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v2/controller/PlatformEntitiesController.java @@ -17,6 +17,7 @@ import io.datahubproject.openapi.generated.MetadataChangeProposal; import io.datahubproject.openapi.util.MappingUtil; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -58,6 +59,7 @@ public void initBinder(WebDataBinder binder) { @PostMapping(value = "/", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity> postEntities( + HttpServletRequest request, @RequestBody @Nonnull List metadataChangeProposals, @RequestParam(required = false, name = "async") Boolean async) { log.info("INGEST PROPOSAL proposal: {}", metadataChangeProposals); @@ -69,6 +71,8 @@ public ResponseEntity> postEntities( systemOperationContext, RequestContext.builder() .buildOpenapi( + actorUrnStr, + request, "postEntities", metadataChangeProposals.stream() .map(MetadataChangeProposal::getEntityType) diff --git a/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v2/controller/TimeseriesController.java b/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v2/controller/TimeseriesController.java index 1c404006d97a4..bb10719bacd3f 100644 --- a/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v2/controller/TimeseriesController.java +++ b/metadata-service/openapi-servlet/src/main/java/io/datahubproject/openapi/v2/controller/TimeseriesController.java @@ -22,6 +22,7 @@ import io.datahubproject.openapi.models.GenericScrollResult; import io.datahubproject.openapi.v2.models.GenericTimeseriesAspect; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import java.net.URISyntaxException; import java.util.List; import java.util.stream.Collectors; @@ -56,6 +57,7 @@ public class TimeseriesController { @GetMapping(value = "/{entityName}/{aspectName}", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity> getAspects( + HttpServletRequest request, @PathVariable("entityName") String entityName, @PathVariable("aspectName") String aspectName, @RequestParam(value = "count", defaultValue = "10") Integer count, @@ -76,7 +78,9 @@ public ResponseEntity> getAspects( OperationContext opContext = OperationContext.asSession( systemOperationContext, - RequestContext.builder().buildOpenapi("getAspects", entityName), + RequestContext.builder() + .buildOpenapi( + authentication.getActor().toUrnStr(), request, "getAspects", entityName), authorizationChain, authentication, true); diff --git a/metadata-service/openapi-servlet/src/test/java/entities/EntitiesControllerTest.java b/metadata-service/openapi-servlet/src/test/java/entities/EntitiesControllerTest.java index 8e70bd507999f..3e352403c88bc 100644 --- a/metadata-service/openapi-servlet/src/test/java/entities/EntitiesControllerTest.java +++ b/metadata-service/openapi-servlet/src/test/java/entities/EntitiesControllerTest.java @@ -214,7 +214,7 @@ public void testIngestDataset() { .build(); datasetAspects.add(glossaryTerms); - _entitiesController.postEntities(datasetAspects, false, false, false); + _entitiesController.postEntities(null, datasetAspects, false, false, false); } // @Test diff --git a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/analytics/Analytics.java b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/analytics/Analytics.java index 7fcaf82e09096..753dd9b807fd1 100644 --- a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/analytics/Analytics.java +++ b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/analytics/Analytics.java @@ -14,6 +14,7 @@ import com.linkedin.restli.server.RestLiServiceException; import com.linkedin.restli.server.annotations.Action; import com.linkedin.restli.server.annotations.ActionParam; +import com.linkedin.restli.server.annotations.Context; import com.linkedin.restli.server.annotations.Optional; import com.linkedin.restli.server.annotations.RestLiSimpleResource; import com.linkedin.restli.server.resources.SimpleResourceTemplate; @@ -28,6 +29,7 @@ import javax.annotation.Nullable; import javax.inject.Inject; import javax.inject.Named; +import javax.servlet.http.HttpServletRequest; import io.datahubproject.metadata.context.OperationContext; import io.datahubproject.metadata.context.RequestContext; @@ -80,7 +82,8 @@ public Task getTimeseriesStats( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to get entity " + entityName); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_GET_TIMESERIES_STATS, entityName), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), + ACTION_GET_TIMESERIES_STATS, entityName), authorizer, auth, true); log.info("Attempting to query timeseries stats"); GetTimeseriesAggregatedStatsResponse resp = new GetTimeseriesAggregatedStatsResponse(); diff --git a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/AspectResource.java b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/AspectResource.java index 8dc73e45846ed..0d9a49d583b57 100644 --- a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/AspectResource.java +++ b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/AspectResource.java @@ -148,7 +148,7 @@ public Task get( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to get aspect for " + urn); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("authorizerChain", urn.getEntityType()), _authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), "authorizerChain", urn.getEntityType()), _authorizer, auth, true); final VersionedAspect aspect = _entityService.getVersionedAspect(opContext, urn, aspectName, version); @@ -199,7 +199,7 @@ public Task getTimeseriesAspectValues( "User is unauthorized to get timeseries aspect for " + urn); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_GET_TIMESERIES_ASPECT, urn.getEntityType()), _authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_GET_TIMESERIES_ASPECT, urn.getEntityType()), _authorizer, auth, true); GetTimeseriesAspectValuesResponse response = new GetTimeseriesAspectValuesResponse(); response.setEntityName(entityName); @@ -280,7 +280,7 @@ private Task ingestProposals( .map(MetadataChangeProposal::getEntityType) .collect(Collectors.toSet()); final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_INGEST_PROPOSAL, entityTypes), _authorizer, authentication, true); + systemOperationContext, RequestContext.builder().buildRestli(authentication.getActor().toUrnStr(), getContext(), ACTION_INGEST_PROPOSAL, entityTypes), _authorizer, authentication, true); // Ingest Authorization Checks List> exceptions = isAPIAuthorized(authentication, _authorizer, ENTITY, @@ -344,7 +344,7 @@ public Task getCount( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to get aspect counts."); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_GET_COUNT, List.of()), _authorizer, authentication, true); + systemOperationContext, RequestContext.builder().buildRestli(authentication.getActor().toUrnStr(), getContext(), ACTION_GET_COUNT, List.of()), _authorizer, authentication, true); return _entityService.getCountAspect(opContext, aspectName, urnLike); }, @@ -373,7 +373,7 @@ public Task restoreIndices( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to update entities."); } - return Utils.restoreIndices(systemOperationContext, + return Utils.restoreIndices(systemOperationContext, getContext(), aspectName, urn, urnLike, start, batchSize, limit, gePitEpochMs, lePitEpochMs, _authorizer, _entityService); }, MetricRegistry.name(this.getClass(), "restoreIndices")); diff --git a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/BatchIngestionRunResource.java b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/BatchIngestionRunResource.java index 970e18cb7bee0..599bbf9ce4df6 100644 --- a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/BatchIngestionRunResource.java +++ b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/BatchIngestionRunResource.java @@ -95,7 +95,7 @@ public Task rollback( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to update entity"); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("rollback", List.of()), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), "rollback", List.of()), authorizer, auth, true); log.info("ROLLBACK RUN runId: {} dry run: {}", runId, dryRun); @@ -171,7 +171,7 @@ public Task describe( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to get entity"); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("describe", List.of()), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), "describe", List.of()), authorizer, auth, true); List summaries = systemMetadataService.findByRunId( diff --git a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/EntityResource.java b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/EntityResource.java index 4ad668d0b1054..e79dda3425682 100644 --- a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/EntityResource.java +++ b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/EntityResource.java @@ -200,7 +200,7 @@ public Task get( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to get entity " + urn); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("restrictedService", urn.getEntityType()), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), "restrictedService", urn.getEntityType()), authorizer, auth, true); return RestliUtil.toTask( () -> { @@ -240,7 +240,7 @@ public Task> batchGet( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to get entities: " + urnStrs); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("batchGet", urnStrs), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), "batchGet", urnStrs), authorizer, auth, true); return RestliUtil.toTask( () -> { @@ -289,7 +289,7 @@ public Task ingest( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to edit entity " + urn); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_INGEST, urn.getEntityType()), authorizer, authentication, true); + systemOperationContext, RequestContext.builder().buildRestli(authentication.getActor().toUrnStr(), getContext(), ACTION_INGEST, urn.getEntityType()), authorizer, authentication, true); try { validateOrThrow(entity); @@ -334,7 +334,7 @@ public Task batchIngest( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to edit entities."); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_BATCH_INGEST, urns.stream() + systemOperationContext, RequestContext.builder().buildRestli(authentication.getActor().toUrnStr(), getContext(), ACTION_BATCH_INGEST, urns.stream() .map(Urn::getEntityType).collect(Collectors.toList())), authorizer, authentication, true); for (Entity entity : entities) { @@ -394,7 +394,7 @@ public Task search( } OperationContext opContext = OperationContext.asSession(systemOperationContext, - RequestContext.builder().buildRestli(ACTION_SEARCH, entityName), authorizer, auth, true) + RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_SEARCH, entityName), authorizer, auth, true) .withSearchFlags(flags -> searchFlags != null ? searchFlags : new SearchFlags().setFulltext(Boolean.TRUE.equals(fulltext))); log.info("GET SEARCH RESULTS for {} with query {}", entityName, input); @@ -434,7 +434,7 @@ public Task searchAcrossEntities( final Authentication auth = AuthenticationContext.getAuthentication(); OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_SEARCH_ACROSS_ENTITIES, entities), authorizer, auth, true) + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_SEARCH_ACROSS_ENTITIES, entities), authorizer, auth, true) .withSearchFlags(flags -> searchFlags != null ? searchFlags : new SearchFlags().setFulltext(true)); List entityList = searchService.getEntitiesToSearch(opContext, entities == null ? Collections.emptyList() : Arrays.asList(entities), count); @@ -478,7 +478,7 @@ public Task scrollAcrossEntities( final Authentication auth = AuthenticationContext.getAuthentication(); OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_SCROLL_ACROSS_ENTITIES, entities), authorizer, auth, true) + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_SCROLL_ACROSS_ENTITIES, entities), authorizer, auth, true) .withSearchFlags(flags -> searchFlags != null ? searchFlags : new SearchFlags().setFulltext(true)); List entityList = searchService.getEntitiesToSearch(opContext, entities == null ? Collections.emptyList() : Arrays.asList(entities), count); @@ -547,7 +547,7 @@ public Task searchAcrossLineage( } OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_SEARCH_ACROSS_LINEAGE, entities), authorizer, auth, true) + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_SEARCH_ACROSS_LINEAGE, entities), authorizer, auth, true) .withSearchFlags(flags -> (searchFlags != null ? searchFlags : new SearchFlags().setFulltext(true)) .setIncludeRestricted(true)) .withLineageFlags(flags -> flags.setStartTimeMillis(startTimeMillis, SetMode.REMOVE_IF_NULL) @@ -606,7 +606,7 @@ public Task scrollAcrossLineage( } OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_SCROLL_ACROSS_LINEAGE, entities), + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_SCROLL_ACROSS_LINEAGE, entities), authorizer, auth, true) .withSearchFlags(flags -> (searchFlags != null ? searchFlags : new SearchFlags().setSkipCache(true)) .setIncludeRestricted(true)) @@ -661,7 +661,7 @@ public Task list( } OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_LIST, entityName), authorizer, auth, true) + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_LIST, entityName), authorizer, auth, true) .withSearchFlags(flags -> new SearchFlags().setFulltext(false)); log.info("GET LIST RESULTS for {} with filter {}", entityName, filter); @@ -702,7 +702,7 @@ public Task autocomplete( } OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_AUTOCOMPLETE, entityName), authorizer, auth, true) + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_AUTOCOMPLETE, entityName), authorizer, auth, true) .withSearchFlags(flags -> searchFlags != null ? searchFlags : flags); return RestliUtil.toTask( @@ -740,7 +740,7 @@ public Task browse( } OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_BROWSE, entityName), authorizer, auth, true) + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_BROWSE, entityName), authorizer, auth, true) .withSearchFlags(flags -> searchFlags != null ? searchFlags : flags); log.info("GET BROWSE RESULTS for {} at path {}", entityName, path); @@ -779,7 +779,7 @@ public Task getBrowsePaths( log.info("GET BROWSE PATHS for {}", urn); OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_GET_BROWSE_PATHS, urn.getEntityType()), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_GET_BROWSE_PATHS, urn.getEntityType()), authorizer, auth, true); return RestliUtil.toTask( () -> new StringArray(entitySearchService.getBrowsePaths(opContext, urnToEntityName(urn), urn)), @@ -848,7 +848,7 @@ public Task deleteEntities( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to delete entities."); } OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("deleteAll", urns), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), "deleteAll", urns), authorizer, auth, true); response.setEntitiesAffected(urns.size()); response.setEntitiesDeleted( @@ -899,7 +899,7 @@ public Task deleteEntity( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to delete entity: " + urnStr); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_DELETE, urn.getEntityType()), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_DELETE, urn.getEntityType()), authorizer, auth, true); return RestliUtil.toTask( () -> { @@ -961,7 +961,7 @@ private Long deleteTimeseriesAspects( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to delete entity " + urn); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("deleteTimeseriesAspects", urn.getEntityType()), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), "deleteTimeseriesAspects", urn.getEntityType()), authorizer, auth, true); // Construct the filter. List criteria = new ArrayList<>(); @@ -1017,7 +1017,7 @@ public Task deleteReferencesTo( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to delete entity " + urnStr); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("deleteReferences", urn.getEntityType()), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), "deleteReferences", urn.getEntityType()), authorizer, auth, true); return RestliUtil.toTask( () -> deleteEntityService.deleteReferencesTo(opContext, urn, dryRun), @@ -1062,7 +1062,7 @@ public Task getTotalEntityCount(@ActionParam(PARAM_ENTITY) @Nonnull String HttpStatus.S_403_FORBIDDEN, "User is unauthorized to get entity counts."); } OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("getTotalEntityCount", entityName), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), "getTotalEntityCount", entityName), authorizer, auth, true); return RestliUtil.toTask(() -> entitySearchService.docCount(opContext, entityName)); } @@ -1080,7 +1080,7 @@ public Task batchGetTotalEntityCount( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to get entity counts."); } OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("batchGetTotalEntityCount", entityNames), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), "batchGetTotalEntityCount", entityNames), authorizer, auth, true); return RestliUtil.toTask( () -> new LongMap(searchService.docCountPerEntity(opContext, Arrays.asList(entityNames)))); } @@ -1103,7 +1103,7 @@ public Task listUrns( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to search."); } OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_LIST_URNS, entityName), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_LIST_URNS, entityName), authorizer, auth, true); log.info("LIST URNS for {} with start {} and count {}", entityName, start, count); return RestliUtil.toTask(() -> { @@ -1145,7 +1145,7 @@ public Task applyRetention( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to apply retention."); } OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_APPLY_RETENTION, resourceSpec.getType()), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_APPLY_RETENTION, resourceSpec.getType()), authorizer, auth, true); return RestliUtil.toTask( () -> entityService.batchApplyRetention(opContext, start, count, attemptWithVersion, aspectName, urn), @@ -1171,7 +1171,7 @@ public Task filter( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to search."); } OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_FILTER, entityName), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_FILTER, entityName), authorizer, auth, true); log.info("FILTER RESULTS for {} with filter {}", entityName, filter); return RestliUtil.toTask( () -> { @@ -1206,7 +1206,7 @@ public Task exists(@ActionParam(PARAM_URN) @Nonnull String urnStr, @Act HttpStatus.S_403_FORBIDDEN, "User is unauthorized check entity existence: " + urnStr); } OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_EXISTS, urn.getEntityType()), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_EXISTS, urn.getEntityType()), authorizer, auth, true); log.info("EXISTS for {}", urnStr); final boolean includeRemoved = includeSoftDelete == null || includeSoftDelete; return RestliUtil.toTask( diff --git a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/EntityV2Resource.java b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/EntityV2Resource.java index af74040e774e5..9052f0240266a 100644 --- a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/EntityV2Resource.java +++ b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/EntityV2Resource.java @@ -79,7 +79,7 @@ public Task get( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to get entity " + urn); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("getEntityV2", urn.getEntityType()), _authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), "getEntityV2", urn.getEntityType()), _authorizer, auth, true); return RestliUtil.toTask( () -> { @@ -123,7 +123,7 @@ public Task> batchGet( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to get entities " + urnStrs); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("getEntityV2", urns.stream().map(Urn::getEntityType).collect(Collectors.toList())), _authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), "getEntityV2", urns.stream().map(Urn::getEntityType).collect(Collectors.toList())), _authorizer, auth, true); if (urns.size() <= 0) { return Task.value(Collections.emptyMap()); diff --git a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/EntityVersionedV2Resource.java b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/EntityVersionedV2Resource.java index 794115ec17d1e..d6c91ba7dcaa3 100644 --- a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/EntityVersionedV2Resource.java +++ b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/entity/EntityVersionedV2Resource.java @@ -88,7 +88,7 @@ public Task> batchGetVersioned( "User is unauthorized to get entities " + versionedUrnStrs); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("authorizerChain", urns.stream() + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), "authorizerChain", urns.stream() .map(Urn::getEntityType).collect(Collectors.toList())), _authorizer, auth, true); log.debug("BATCH GET VERSIONED V2 {}", versionedUrnStrs); diff --git a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/operations/OperationsResource.java b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/operations/OperationsResource.java index c92f7207aa655..42d0bf11c505d 100644 --- a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/operations/OperationsResource.java +++ b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/operations/OperationsResource.java @@ -107,7 +107,7 @@ public Task restoreIndices( @ActionParam("gePitEpochMs") @Optional @Nullable Long gePitEpochMs, @ActionParam("lePitEpochMs") @Optional @Nullable Long lePitEpochMs) { return RestliUtil.toTask( - () -> Utils.restoreIndices(systemOperationContext, + () -> Utils.restoreIndices(systemOperationContext, getContext(), aspectName, urn, urnLike, start, batchSize, limit, gePitEpochMs, lePitEpochMs, _authorizer, _entityService), MetricRegistry.name(this.getClass(), "restoreIndices")); } @@ -202,7 +202,7 @@ public Task getIndexSizes() { HttpStatus.S_403_FORBIDDEN, "User is unauthorized to get index sizes."); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_GET_INDEX_SIZES, List.of()), _authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_GET_INDEX_SIZES, List.of()), _authorizer, auth, true); TimeseriesIndicesSizesResult result = new TimeseriesIndicesSizesResult(); result.setIndexSizes( @@ -232,7 +232,7 @@ String executeTruncateTimeseriesAspect( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to truncate timeseries index"); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("executeTruncateTimeseriesAspect", entityType), _authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), "executeTruncateTimeseriesAspect", entityType), _authorizer, auth, true); if (forceDeleteByQuery != null && forceDeleteByQuery.equals(forceReindex)) { return "please only set forceReindex OR forceDeleteByQuery flags"; diff --git a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/operations/Utils.java b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/operations/Utils.java index 2c411f9ad960e..54c1029edcab0 100644 --- a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/operations/Utils.java +++ b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/operations/Utils.java @@ -13,6 +13,7 @@ import com.linkedin.metadata.entity.restoreindices.RestoreIndicesArgs; import com.linkedin.metadata.entity.restoreindices.RestoreIndicesResult; import com.linkedin.restli.common.HttpStatus; +import com.linkedin.restli.server.ResourceContext; import com.linkedin.restli.server.RestLiServiceException; import java.util.HashMap; import java.util.List; @@ -32,7 +33,8 @@ public class Utils { private Utils() {} public static String restoreIndices( - @Nonnull OperationContext systemOperationContext, + @Nonnull OperationContext systemOperationContext, + @Nonnull ResourceContext resourceContext, @Nonnull String aspectName, @Nullable String urn, @Nullable String urnLike, @@ -59,7 +61,7 @@ public static String restoreIndices( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to restore indices."); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli("restoreIndices", List.of()), authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), resourceContext, "restoreIndices", List.of()), authorizer, auth, true); RestoreIndicesArgs args = new RestoreIndicesArgs() diff --git a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/usage/UsageStats.java b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/usage/UsageStats.java index 82e0e000a31be..518dfecd57680 100644 --- a/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/usage/UsageStats.java +++ b/metadata-service/restli-servlet-impl/src/main/java/com/linkedin/metadata/resources/usage/UsageStats.java @@ -141,7 +141,7 @@ public Task batchIngest(@ActionParam(PARAM_BUCKETS) @Nonnull UsageAggregat HttpStatus.S_403_FORBIDDEN, "User is unauthorized to edit entities."); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_BATCH_INGEST, urns.stream() + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_BATCH_INGEST, urns.stream() .map(Urn::getEntityType).collect(Collectors.toList())), _authorizer, auth, true); for (UsageAggregation agg : buckets) { @@ -180,7 +180,7 @@ public Task query( HttpStatus.S_403_FORBIDDEN, "User is unauthorized to query usage."); } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_QUERY, resourceUrn.getEntityType()), _authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_QUERY, resourceUrn.getEntityType()), _authorizer, auth, true); return UsageServiceUtil.query(opContext, _timeseriesAspectService, resource, duration, startTime, endTime, maxBuckets); }, @@ -207,7 +207,7 @@ public Task queryRange( } final OperationContext opContext = OperationContext.asSession( - systemOperationContext, RequestContext.builder().buildRestli(ACTION_QUERY_RANGE, resourceUrn.getEntityType()), _authorizer, auth, true); + systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(), ACTION_QUERY_RANGE, resourceUrn.getEntityType()), _authorizer, auth, true); return RestliUtil.toTask( () -> UsageServiceUtil.queryRange(opContext, _timeseriesAspectService, resource, duration, range), MetricRegistry.name(this.getClass(), "queryRange"));