Search in sources :

Example 21 with InboundMessageContext

use of org.wso2.carbon.apimgt.gateway.inbound.InboundMessageContext in project carbon-apimgt by wso2.

the class InboundWebsocketProcessorUtil method validateScopes.

/**
 * Validates scopes for subscription operations.
 *
 * @param inboundMessageContext InboundMessageContext
 * @param subscriptionOperation Subscription operation
 * @param operationId           GraphQL message Id
 * @return InboundProcessorResponseDTO
 */
public static InboundProcessorResponseDTO validateScopes(InboundMessageContext inboundMessageContext, String subscriptionOperation, String operationId) {
    InboundProcessorResponseDTO responseDTO = new GraphQLProcessorResponseDTO();
    // validate scopes based on subscription payload
    try {
        if (!InboundWebsocketProcessorUtil.authorizeGraphQLSubscriptionEvents(subscriptionOperation, inboundMessageContext)) {
            String errorMessage = WebSocketApiConstants.FrameErrorConstants.RESOURCE_FORBIDDEN_ERROR_MESSAGE + StringUtils.SPACE + subscriptionOperation;
            log.error(errorMessage);
            responseDTO = InboundWebsocketProcessorUtil.getGraphQLFrameErrorDTO(WebSocketApiConstants.FrameErrorConstants.RESOURCE_FORBIDDEN_ERROR, errorMessage, false, operationId);
        }
    } catch (APIManagementException e) {
        log.error(WebSocketApiConstants.FrameErrorConstants.API_AUTH_GENERAL_MESSAGE, e);
        responseDTO = InboundWebsocketProcessorUtil.getFrameErrorDTO(WebSocketApiConstants.FrameErrorConstants.API_AUTH_GENERAL_ERROR, WebSocketApiConstants.FrameErrorConstants.API_AUTH_GENERAL_MESSAGE, true);
    } catch (APISecurityException e) {
        log.error(WebSocketApiConstants.FrameErrorConstants.RESOURCE_FORBIDDEN_ERROR_MESSAGE, e);
        responseDTO = InboundWebsocketProcessorUtil.getGraphQLFrameErrorDTO(WebSocketApiConstants.FrameErrorConstants.RESOURCE_FORBIDDEN_ERROR, e.getMessage(), false, operationId);
    }
    return responseDTO;
}
Also used : APISecurityException(org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException) GraphQLProcessorResponseDTO(org.wso2.carbon.apimgt.gateway.inbound.websocket.GraphQLProcessorResponseDTO) APIManagementException(org.wso2.carbon.apimgt.api.APIManagementException) InboundProcessorResponseDTO(org.wso2.carbon.apimgt.gateway.inbound.websocket.InboundProcessorResponseDTO)

Example 22 with InboundMessageContext

use of org.wso2.carbon.apimgt.gateway.inbound.InboundMessageContext in project carbon-apimgt by wso2.

the class InboundWebSocketProcessor method handleHandshake.

/**
 * This method process websocket handshake and extract necessary API information from the channel context and
 * request. Finally, hand over the processing to relevant handshake processor for authentication etc.
 *
 * @param req                   Handshake request
 * @param ctx                   Channel pipeline context
 * @param inboundMessageContext InboundMessageContext
 * @return InboundProcessorResponseDTO with handshake processing response
 */
public InboundProcessorResponseDTO handleHandshake(FullHttpRequest req, ChannelHandlerContext ctx, InboundMessageContext inboundMessageContext) {
    InboundProcessorResponseDTO inboundProcessorResponseDTO;
    try {
        HandshakeProcessor handshakeProcessor = new HandshakeProcessor();
        setUris(req, inboundMessageContext);
        InboundWebsocketProcessorUtil.setTenantDomainToContext(inboundMessageContext);
        setMatchingResource(ctx, req, inboundMessageContext);
        String userAgent = req.headers().get(HttpHeaders.USER_AGENT);
        // '-' is used for empty values to avoid possible errors in DAS side.
        // Required headers are stored one by one as validateOAuthHeader()
        // removes some headers from the request
        userAgent = userAgent != null ? userAgent : "-";
        inboundMessageContext.getRequestHeaders().put(HttpHeaders.USER_AGENT, userAgent);
        PrivilegedCarbonContext.startTenantFlow();
        PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(inboundMessageContext.getTenantDomain(), true);
        if (validateOAuthHeader(req, inboundMessageContext)) {
            setRequestHeaders(req, inboundMessageContext);
            inboundMessageContext.getRequestHeaders().put(HttpHeaders.AUTHORIZATION, req.headers().get(HttpHeaders.AUTHORIZATION));
            inboundProcessorResponseDTO = handshakeProcessor.processHandshake(inboundMessageContext);
        } else {
            String errorMessage = "No Authorization Header or access_token query parameter present";
            log.error(errorMessage + " in request for the websocket context " + inboundMessageContext.getApiContext());
            inboundProcessorResponseDTO = InboundWebsocketProcessorUtil.getHandshakeErrorDTO(WebSocketApiConstants.HandshakeErrorConstants.API_AUTH_ERROR, errorMessage);
        }
        publishHandshakeAuthErrorEvent(ctx, inboundProcessorResponseDTO.getErrorMessage());
        return inboundProcessorResponseDTO;
    } catch (APISecurityException e) {
        log.error("Authentication Failure for the websocket context: " + inboundMessageContext.getApiContext() + e.getMessage());
        inboundProcessorResponseDTO = InboundWebsocketProcessorUtil.getHandshakeErrorDTO(WebSocketApiConstants.HandshakeErrorConstants.API_AUTH_ERROR, e.getMessage());
        publishHandshakeAuthErrorEvent(ctx, e.getMessage());
    } catch (WebSocketApiException e) {
        log.error(e.getMessage());
        inboundProcessorResponseDTO = InboundWebsocketProcessorUtil.getHandshakeErrorDTO(WebSocketApiConstants.HandshakeErrorConstants.INTERNAL_SERVER_ERROR, e.getMessage());
    } catch (ResourceNotFoundException e) {
        log.error(e.getMessage());
        inboundProcessorResponseDTO = InboundWebsocketProcessorUtil.getHandshakeErrorDTO(WebSocketApiConstants.HandshakeErrorConstants.RESOURCE_NOT_FOUND_ERROR, e.getMessage());
        publishResourceNotFoundEvent(ctx);
    }
    return inboundProcessorResponseDTO;
}
Also used : APISecurityException(org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException) WebSocketApiException(org.wso2.carbon.apimgt.gateway.handlers.streaming.websocket.WebSocketApiException) ResourceNotFoundException(org.wso2.carbon.apimgt.gateway.handlers.security.ResourceNotFoundException) HandshakeProcessor(org.wso2.carbon.apimgt.gateway.inbound.websocket.handshake.HandshakeProcessor)

Example 23 with InboundMessageContext

use of org.wso2.carbon.apimgt.gateway.inbound.InboundMessageContext in project carbon-apimgt by wso2.

the class InboundWebSocketProcessor method setUris.

/**
 * Extract full request path from the request and update InboundMessageContext.
 *
 * @param req                   Request object
 * @param inboundMessageContext InboundMessageContext
 */
private void setUris(FullHttpRequest req, InboundMessageContext inboundMessageContext) throws WebSocketApiException {
    try {
        String fullRequestPath = req.uri();
        inboundMessageContext.setFullRequestPath(req.uri());
        URI uriTemp;
        uriTemp = new URI(fullRequestPath);
        String requestPath = new URI(uriTemp.getScheme(), uriTemp.getAuthority(), uriTemp.getPath(), null, uriTemp.getFragment()).toString();
        if (requestPath.endsWith(WebSocketApiConstants.URL_SEPARATOR)) {
            requestPath = requestPath.substring(0, requestPath.length() - 1);
        }
        inboundMessageContext.setRequestPath(requestPath);
        if (log.isDebugEnabled()) {
            log.debug("Websocket API fullRequestPath = " + inboundMessageContext.getRequestPath());
        }
    } catch (URISyntaxException e) {
        throw new WebSocketApiException("Error while parsing uri: " + e.getMessage());
    }
}
Also used : WebSocketApiException(org.wso2.carbon.apimgt.gateway.handlers.streaming.websocket.WebSocketApiException) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI)

Example 24 with InboundMessageContext

use of org.wso2.carbon.apimgt.gateway.inbound.InboundMessageContext in project carbon-apimgt by wso2.

the class GraphQLRequestProcessor method validateQueryComplexity.

/**
 * Validate query complexity of graphql subscription payload.
 *
 * @param subscriptionAnalyzer  Query complexity and depth analyzer for subscription operations
 * @param inboundMessageContext InboundMessageContext
 * @param payload               GraphQL payload
 * @param operationId           Graphql message id
 * @return GraphQLProcessorResponseDTO
 */
private GraphQLProcessorResponseDTO validateQueryComplexity(SubscriptionAnalyzer subscriptionAnalyzer, InboundMessageContext inboundMessageContext, String payload, String operationId) {
    GraphQLProcessorResponseDTO responseDTO = new GraphQLProcessorResponseDTO();
    responseDTO.setId(operationId);
    try {
        QueryAnalyzerResponseDTO queryAnalyzerResponseDTO = subscriptionAnalyzer.analyseSubscriptionQueryComplexity(payload, inboundMessageContext.getInfoDTO().getGraphQLMaxComplexity());
        if (!queryAnalyzerResponseDTO.isSuccess() && !queryAnalyzerResponseDTO.getErrorList().isEmpty()) {
            List<String> errorList = queryAnalyzerResponseDTO.getErrorList();
            log.error("Query complexity validation failed for: " + payload + " errors: " + errorList.toString());
            responseDTO.setError(true);
            responseDTO.setErrorCode(WebSocketApiConstants.FrameErrorConstants.GRAPHQL_QUERY_TOO_COMPLEX);
            responseDTO.setErrorMessage(WebSocketApiConstants.FrameErrorConstants.GRAPHQL_QUERY_TOO_COMPLEX_MESSAGE + " : " + queryAnalyzerResponseDTO.getErrorList().toString());
            return responseDTO;
        }
    } catch (APIManagementException e) {
        log.error("Error while validating query complexity for: " + payload, e);
        responseDTO.setError(true);
        responseDTO.setErrorMessage(e.getMessage());
        responseDTO.setErrorCode(WebSocketApiConstants.FrameErrorConstants.INTERNAL_SERVER_ERROR);
    }
    return responseDTO;
}
Also used : GraphQLProcessorResponseDTO(org.wso2.carbon.apimgt.gateway.inbound.websocket.GraphQLProcessorResponseDTO) APIManagementException(org.wso2.carbon.apimgt.api.APIManagementException) QueryAnalyzerResponseDTO(org.wso2.carbon.apimgt.common.gateway.dto.QueryAnalyzerResponseDTO)

Example 25 with InboundMessageContext

use of org.wso2.carbon.apimgt.gateway.inbound.InboundMessageContext in project carbon-apimgt by wso2.

the class GraphQLRequestProcessorTest method testHandleRequestScopeValidationSkipWhenSecurityDisabled.

@Test
public void testHandleRequestScopeValidationSkipWhenSecurityDisabled() throws Exception {
    InboundMessageContext inboundMessageContext = new InboundMessageContext();
    int msgSize = 100;
    String msgText = "{\"id\":\"1\",\"type\":\"start\",\"payload\":{\"variables\":{},\"extensions\":{}," + "\"operationName\":null,\"query\":\"subscription {\\n  " + "liftStatusChange {\\n    id\\n    name\\n }\\n}\\n\"}}";
    PowerMockito.mockStatic(InboundWebsocketProcessorUtil.class);
    InboundProcessorResponseDTO responseDTO = new InboundProcessorResponseDTO();
    PowerMockito.when(InboundWebsocketProcessorUtil.authenticateToken(inboundMessageContext)).thenReturn(responseDTO);
    // Get schema and parse
    String graphqlDirPath = "graphQL" + File.separator;
    String relativePath = graphqlDirPath + "schema_with_additional_props.graphql";
    String schemaString = IOUtils.toString(getClass().getClassLoader().getResourceAsStream(relativePath));
    SchemaParser schemaParser = new SchemaParser();
    TypeDefinitionRegistry registry = schemaParser.parse(schemaString);
    GraphQLSchema schema = UnExecutableSchemaGenerator.makeUnExecutableSchema(registry);
    GraphQLSchemaDTO schemaDTO = new GraphQLSchemaDTO(schema, registry);
    inboundMessageContext.setGraphQLSchemaDTO(schemaDTO);
    // VerbInfoDTO with security disabled
    VerbInfoDTO verbInfoDTO = new VerbInfoDTO();
    verbInfoDTO.setHttpVerb("SUBSCRIPTION");
    verbInfoDTO.setThrottling("Unlimited");
    verbInfoDTO.setAuthType("None");
    PowerMockito.when(InboundWebsocketProcessorUtil.findMatchingVerb("liftStatusChange", inboundMessageContext)).thenReturn(verbInfoDTO);
    // Creating response for scope validation
    GraphQLProcessorResponseDTO graphQLProcessorResponseDTO = new GraphQLProcessorResponseDTO();
    graphQLProcessorResponseDTO.setError(true);
    graphQLProcessorResponseDTO.setErrorCode(WebSocketApiConstants.FrameErrorConstants.RESOURCE_FORBIDDEN_ERROR);
    graphQLProcessorResponseDTO.setErrorMessage("User is NOT authorized to access the Resource");
    graphQLProcessorResponseDTO.setCloseConnection(false);
    graphQLProcessorResponseDTO.setId("1");
    PowerMockito.when(InboundWebsocketProcessorUtil.validateScopes(inboundMessageContext, "liftStatusChange", "1")).thenReturn(graphQLProcessorResponseDTO);
    PowerMockito.when(InboundWebsocketProcessorUtil.doThrottleForGraphQL(msgSize, verbInfoDTO, inboundMessageContext, "1")).thenReturn(responseDTO);
    GraphQLRequestProcessor graphQLRequestProcessor = new GraphQLRequestProcessor();
    InboundProcessorResponseDTO processorResponseDTO = graphQLRequestProcessor.handleRequest(msgSize, msgText, inboundMessageContext);
    Assert.assertFalse(processorResponseDTO.isError());
    Assert.assertNull(processorResponseDTO.getErrorMessage());
    Assert.assertNotEquals(processorResponseDTO.getErrorMessage(), "User is NOT authorized to access the Resource");
}
Also used : GraphQLProcessorResponseDTO(org.wso2.carbon.apimgt.gateway.inbound.websocket.GraphQLProcessorResponseDTO) VerbInfoDTO(org.wso2.carbon.apimgt.impl.dto.VerbInfoDTO) InboundProcessorResponseDTO(org.wso2.carbon.apimgt.gateway.inbound.websocket.InboundProcessorResponseDTO) TypeDefinitionRegistry(graphql.schema.idl.TypeDefinitionRegistry) InboundMessageContext(org.wso2.carbon.apimgt.gateway.inbound.InboundMessageContext) GraphQLSchemaDTO(org.wso2.carbon.apimgt.api.gateway.GraphQLSchemaDTO) SchemaParser(graphql.schema.idl.SchemaParser) GraphQLSchema(graphql.schema.GraphQLSchema) Test(org.junit.Test) PrepareForTest(org.powermock.core.classloader.annotations.PrepareForTest)

Aggregations

InboundProcessorResponseDTO (org.wso2.carbon.apimgt.gateway.inbound.websocket.InboundProcessorResponseDTO)32 InboundMessageContext (org.wso2.carbon.apimgt.gateway.inbound.InboundMessageContext)31 Test (org.junit.Test)26 PrepareForTest (org.powermock.core.classloader.annotations.PrepareForTest)26 VerbInfoDTO (org.wso2.carbon.apimgt.impl.dto.VerbInfoDTO)15 GraphQLProcessorResponseDTO (org.wso2.carbon.apimgt.gateway.inbound.websocket.GraphQLProcessorResponseDTO)12 APIKeyValidationInfoDTO (org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO)8 GraphQLOperationDTO (org.wso2.carbon.apimgt.gateway.dto.GraphQLOperationDTO)7 GraphQLSchema (graphql.schema.GraphQLSchema)6 SchemaParser (graphql.schema.idl.SchemaParser)6 TypeDefinitionRegistry (graphql.schema.idl.TypeDefinitionRegistry)6 JSONObject (org.json.simple.JSONObject)6 JSONParser (org.json.simple.parser.JSONParser)6 GraphQLSchemaDTO (org.wso2.carbon.apimgt.api.gateway.GraphQLSchemaDTO)6 TextWebSocketFrame (io.netty.handler.codec.http.websocketx.TextWebSocketFrame)5 APIManagementException (org.wso2.carbon.apimgt.api.APIManagementException)5 APISecurityException (org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException)5 WebSocketApiException (org.wso2.carbon.apimgt.gateway.handlers.streaming.websocket.WebSocketApiException)4 CloseWebSocketFrame (io.netty.handler.codec.http.websocketx.CloseWebSocketFrame)3 WebSocketFrame (io.netty.handler.codec.http.websocketx.WebSocketFrame)3