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;
}
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;
}
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());
}
}
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;
}
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");
}
Aggregations