Skip to content

Commit

Permalink
Mandate Enforcer availability for the Router
Browse files Browse the repository at this point in the history
  • Loading branch information
pubudu538 committed Mar 31, 2024
1 parent 32435dc commit 2b32250
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 23 deletions.
1 change: 0 additions & 1 deletion adapter/internal/oasparser/envoyconf/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ const (
const (
// healthEndpointResponse - response from the health endpoint
healthEndpointResponse = "{\"status\": \"healthy\"}"
readyEndpointResponse = "{\"status\": \"ready\"}"
)

const (
Expand Down
26 changes: 4 additions & 22 deletions adapter/internal/oasparser/envoyconf/routes_with_clusters.go
Original file line number Diff line number Diff line change
Expand Up @@ -1333,36 +1333,18 @@ func CreateReadyEndpoint() *routev3.Route {
Operation: readyPath,
}

perFilterConfig := extAuthService.ExtAuthzPerRoute{
Override: &extAuthService.ExtAuthzPerRoute_Disabled{
Disabled: true,
},
}

data, _ := proto.Marshal(&perFilterConfig)
filter := &any.Any{
TypeUrl: extAuthzPerRouteName,
Value: data,
}

router = routev3.Route{
Name: readyPath, //Categorize routes with same base path
Match: match,
Action: &routev3.Route_DirectResponse{
DirectResponse: &routev3.DirectResponseAction{
Status: 200,
Body: &corev3.DataSource{
Specifier: &corev3.DataSource_InlineString{
InlineString: readyEndpointResponse,
},
Action: &routev3.Route_Route{
Route: &routev3.RouteAction{
ClusterSpecifier: &routev3.RouteAction_Cluster{
Cluster: extAuthzClusterName,
},
},
},
Metadata: nil,
Decorator: decorator,
TypedPerFilterConfig: map[string]*any.Any{
wellknown.HTTPExternalAuthorization: filter,
},
}
return &router
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,4 +280,13 @@ public static class Optionality {
public static final String OPTIONAL = "optional";
}

/**
* Holds values related to readiness check.
*/
public static class ReadinessCheck {
public static final String ENDPOINT = "/ready";
public static final String RESPONSE_KEY = "status";
public static final String RESPONSE_VALUE = "ready";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import io.grpc.stub.StreamObserver;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import org.json.JSONObject;
import org.apache.logging.log4j.ThreadContext;
import org.wso2.apk.enforcer.api.ResponseObject;
import org.wso2.apk.enforcer.constants.APIConstants;
Expand Down Expand Up @@ -121,6 +122,11 @@ private CheckResponse buildResponse(CheckRequest request, ResponseObject respons
HttpStatus status = HttpStatus.newBuilder().setCodeValue(responseObject.getStatusCode()).build();
deniedResponsePreparer.setStatus(status);

// handle the response of the '/ready' request
if (APIConstants.ReadinessCheck.ENDPOINT.equals(responseObject.getRequestPath())) {
return buildReadyCheckResponse(checkResponseBuilder, status);
}

// set body content
if (responseObject.getResponsePayload() != null) {
deniedResponsePreparer.setBody(responseObject.getResponsePayload());
Expand Down Expand Up @@ -261,4 +267,40 @@ private String constructQueryParamString(boolean removeAllQueryParams, String re
private void addMetadata(Struct.Builder structBuilder, String key, String value) {
structBuilder.putFields(key, Value.newBuilder().setStringValue(value).build());
}

/**
* This method builds the CheckResponse to be returned as response to '/ready'
* request of router
*
* @param responseBuilder CheckResponse.Builder object
* @param status HttpStatus object
* @return CheckResponse with body {"status":"ready"} and status code 200 OK.
*/
private CheckResponse buildReadyCheckResponse(CheckResponse.Builder responseBuilder, HttpStatus status) {
/*
* The DeniedResponsePreparer.Builder is used to send a direct response from
* ext-authz
* with status 200 and body {"status":"ready"}
*/

JSONObject responseJson = new JSONObject();
responseJson.put(APIConstants.ReadinessCheck.RESPONSE_KEY, APIConstants.ReadinessCheck.RESPONSE_VALUE);
HeaderValueOption headerValueOption = HeaderValueOption.newBuilder().setHeader(HeaderValue.newBuilder()
.setKey(APIConstants.CONTENT_TYPE_HEADER).setValue(APIConstants.APPLICATION_JSON).build())
.build();

DeniedResponsePreparer deniedResponsePreparer = new DeniedResponsePreparer(DeniedHttpResponse.newBuilder());
deniedResponsePreparer.addHeaders(headerValueOption);
deniedResponsePreparer.setStatus(status);
deniedResponsePreparer.setBody(responseJson.toString());

Struct.Builder metadataStructBuilder = Struct.newBuilder();
addMetadata(metadataStructBuilder, MetadataConstants.APK_ENFORCER_REPLY, "Ok");

return CheckResponse.newBuilder()
.setDynamicMetadata(metadataStructBuilder.build())
.setStatus(Status.newBuilder().setCode(Code.INTERNAL_VALUE).build())
.setDeniedResponse(deniedResponsePreparer.build())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ public class HttpRequestHandler implements RequestHandler<CheckRequest, Response
private static final Logger logger = LogManager.getLogger(RequestHandler.class);

public ResponseObject process(CheckRequest request) {

// Handle the '/ready' request separately.
if (APIConstants.ReadinessCheck.ENDPOINT.equals(request.getAttributes().getRequest().getHttp().getPath())) {
return processReadyRequest();
}

API matchedAPI = APIFactory.getInstance().getMatchedAPI(request);
if (matchedAPI == null) {
ResponseObject responseObject = new ResponseObject();
Expand Down Expand Up @@ -146,4 +152,17 @@ private RequestContext buildRequestContext(API api, CheckRequest request) {
.requestTimeStamp(requestTimeInMillis).pathTemplate(pathTemplate).requestPayload(requestPayload)
.build();
}

/**
* This method handles the processing of '/ready' request sent by router.
*
* @return ResponseObject with status 200
*/
private ResponseObject processReadyRequest() {
ResponseObject responseObject = new ResponseObject();
responseObject.setStatusCode(APIConstants.StatusCodes.OK.getCode());
responseObject.setRequestPath(APIConstants.ReadinessCheck.ENDPOINT);
responseObject.setDirectResponse(true);
return responseObject;
}
}

0 comments on commit 2b32250

Please sign in to comment.