Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into fix/revert-proxy-change
Browse files Browse the repository at this point in the history
  • Loading branch information
imesh94 committed Oct 28, 2024
2 parents ca36673 + ef576f1 commit f5a8866
Show file tree
Hide file tree
Showing 15 changed files with 487 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -812,4 +812,26 @@ public int performConfigIntegerValueCheck(String key, int defaultValue) {
}
return defaultValue;
}

/**
* Get external traffic header name.
* This header should be set by the load balancer to identify the external traffic.
*
* @return String
*/
public String getExternalTrafficHeaderName() {

return ((String) getConfigElementFromKey(CommonConstants.EXTERNAL_TRAFFIC_HEADER_NAME)).trim();
}

/**
* Get external traffic expected header value.
* If this value is set in the header identified by the header name, the traffic is considered as external.
*
* @return String
*/
public String getExternalTrafficExpectedValue() {

return ((String) getConfigElementFromKey(CommonConstants.EXTERNAL_TRAFFIC_EXPECTED_VALUE)).trim();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public class CommonConstants {
public static final String VALIDATE_ACCOUNTS_ON_RETRIEVAL = "BNR.ValidateAccountsOnRetrieval";
public static final String ENABLE_CONSENT_REVOCATION = "BNR.EnableConsentRevocation";
public static final String CUSTOMER_TYPE_SELECTION_METHOD = "BNR.CustomerTypeSelectionMethod";
public static final String EXTERNAL_TRAFFIC_HEADER_NAME = "ExternalTraffic.HeaderName";
public static final String EXTERNAL_TRAFFIC_EXPECTED_VALUE = "ExternalTraffic.ExpectedValue";

// Http related constants
public static final String POST_METHOD = "POST";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,20 @@ public void testGetBNRCustomerTypeSelectionMethod() {
Assert.assertEquals(openBankingCDSConfigParser.getBNRCustomerTypeSelectionMethod(), "profile_selection");
}

@Test(priority = 8)
public void testGetExternalTrafficHeaderName() {
String dummyConfigFile = absolutePathForTestResources + "/open-banking-cds.xml";
OpenBankingCDSConfigParser openBankingCDSConfigParser = OpenBankingCDSConfigParser.getInstance(dummyConfigFile);
Assert.assertEquals(openBankingCDSConfigParser.getExternalTrafficHeaderName(), "X-External-Traffic");
}

@Test(priority = 8)
public void testGetExternalTrafficExpectedValue() {
String dummyConfigFile = absolutePathForTestResources + "/open-banking-cds.xml";
OpenBankingCDSConfigParser openBankingCDSConfigParser = OpenBankingCDSConfigParser.getInstance(dummyConfigFile);
Assert.assertEquals(openBankingCDSConfigParser.getExternalTrafficExpectedValue(), "true");
}

private void injectEnvironmentVariable(String key, String value)
throws ReflectiveOperationException {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,8 @@
<DisclosureOptionsManagement>
<Enable>true</Enable>
</DisclosureOptionsManagement>
<ExternalTraffic>
<HeaderName>X-External-Traffic</HeaderName>
<ExpectedValue>true</ExpectedValue>
</ExternalTraffic>
</Server>
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public class CDSConsentEventExecutor implements OBEventExecutor {
private static final String USER_ID_KEY = "userId";
private static final String STATUS_KEY = "status";
private static final String EXPIRY_TIME_KEY = "expiryTime";
private static final ConcurrentLinkedDeque<String> publishedRequestUriKeyQueue = new ConcurrentLinkedDeque<>();
private static final ConcurrentLinkedDeque<String> publishedEventIdentifierQueue = new ConcurrentLinkedDeque<>();

@Override
public void processEvent(OBEvent obEvent) {
Expand Down Expand Up @@ -160,12 +160,13 @@ public void processEvent(OBEvent obEvent) {

log.debug("Publishing consent data for authorisation metrics.");
String consentId = (String) eventData.get(CONSENT_ID);
ConsentStatusEnum consentStatus = getConsentStatusForEventType(obEvent.getEventType());
AuthorisationFlowTypeEnum authFlowType = getAuthFlowTypeForEventType(obEvent.getEventType());
String requestUriKey = getRequestUriKeyFromConsentResource(consentResource, detailedConsentResource);
if (requestUriKey != null && publishedRequestUriKeyQueue.contains(requestUriKey)) {
String eventType = obEvent.getEventType();
ConsentStatusEnum consentStatus = getConsentStatusForEventType(eventType);
AuthorisationFlowTypeEnum authFlowType = getAuthFlowTypeForEventType(eventType);
String eventIdentifier = getEventIdentifier(consentResource, detailedConsentResource, eventType);
if (eventIdentifier != null && publishedEventIdentifierQueue.contains(eventIdentifier)) {
if (log.isDebugEnabled()) {
log.debug("Skipping authorisation data publishing for requestUriKey: " + requestUriKey +
log.debug("Skipping authorisation data publishing for event identifier: " + eventIdentifier +
" as it has already been published.");
}
return;
Expand All @@ -190,7 +191,7 @@ public void processEvent(OBEvent obEvent) {
consentStatus, authFlowType, customerProfile, consentDurationType);

dataPublishingService.publishAuthorisationData(authorisationData);
addToPublishedRequestUriKeyQueue(requestUriKey);
addToPublishedEventIdentifierQueue(eventIdentifier);
}

}
Expand Down Expand Up @@ -390,32 +391,32 @@ private AuthorisationFlowTypeEnum getAuthFlowTypeForEventType(String eventType)
}

/**
* Add the request uri key to the published data queue.
* Add the event identifier to the published data queue.
* If the queue is full, oldest key is removed.
* 20 keys are maintained in the queue to handle simultaneous consent state change events.
*
* @param requestUriKey request uri key coming as a consent attribute
* @param eventIdentifier request uri key coming as a consent attribute + event type to identify a unique event.
*/
private void addToPublishedRequestUriKeyQueue(String requestUriKey) {
private void addToPublishedEventIdentifierQueue(String eventIdentifier) {

if (StringUtils.isBlank(requestUriKey)) {
if (StringUtils.isBlank(eventIdentifier)) {
return;
}
if (publishedRequestUriKeyQueue.size() >= 20) {
publishedRequestUriKeyQueue.pollFirst();
if (publishedEventIdentifierQueue.size() >= 20) {
publishedEventIdentifierQueue.pollFirst();
}
publishedRequestUriKeyQueue.addLast(requestUriKey);
publishedEventIdentifierQueue.addLast(eventIdentifier);
}

private String getRequestUriKeyFromConsentResource(ConsentResource consentResource,
DetailedConsentResource detailedConsentResource) {
private String getEventIdentifier(ConsentResource consentResource, DetailedConsentResource detailedConsentResource,
String eventType) {

Map<String, String> consentAttributes = null;
if (consentResource != null) {
consentAttributes = consentResource.getConsentAttributes();
} else if (detailedConsentResource != null) {
consentAttributes = detailedConsentResource.getConsentAttributes();
}
return consentAttributes != null ? consentAttributes.get(REQUEST_URI_KEY) : null;
return consentAttributes != null ? (consentAttributes.get(REQUEST_URI_KEY) + ":" + eventType) : null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
* <p>
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.openbanking.cds.identity.filter;

import org.wso2.openbanking.cds.identity.utils.CDSIdentityConstants;

import javax.servlet.ServletRequest;

/**
* Authorize Data Publishing Filter.
* Implements custom logic related to publishing /authorize request data.
*/
public class AuthorizeDataPublishingFilter extends InfoSecDataPublishingFilter {

@Override
public boolean shouldPublishCurrentRequestData(ServletRequest request) {

// If the sessionDataKey query parameter is present, it is an internal redirect and should not be published.
return request.getParameter(CDSIdentityConstants.SESSION_DATA_KEY_PARAMETER) == null &&
super.shouldPublishCurrentRequestData(request);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/**
* Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
*
* <p>
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
Expand All @@ -26,7 +26,9 @@
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.openbanking.cds.common.config.OpenBankingCDSConfigParser;
import org.wso2.openbanking.cds.common.data.publisher.CDSDataPublishingService;
import org.wso2.openbanking.cds.common.utils.CommonConstants;
import org.wso2.openbanking.cds.identity.filter.constants.CDSFilterConstants;

import java.io.IOException;
Expand Down Expand Up @@ -54,6 +56,11 @@
public class InfoSecDataPublishingFilter implements Filter {

private static final Log LOG = LogFactory.getLog(InfoSecDataPublishingFilter.class);
private final Map<String, Object> configMap = OpenBankingCDSConfigParser.getInstance().getConfiguration();
private final String externalTrafficHeaderName = (String) configMap.get(CommonConstants
.EXTERNAL_TRAFFIC_HEADER_NAME);
private final String expectedExternalTrafficHeaderValue = (String) configMap.get(CommonConstants
.EXTERNAL_TRAFFIC_EXPECTED_VALUE);

@Override
public void init(FilterConfig filterConfig) {
Expand Down Expand Up @@ -83,7 +90,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
public void publishReportingData(HttpServletRequest request, HttpServletResponse response) {

if (Boolean.parseBoolean((String) OpenBankingConfigParser.getInstance().getConfiguration()
.get(DataPublishingConstants.DATA_PUBLISHING_ENABLED))) {
.get(DataPublishingConstants.DATA_PUBLISHING_ENABLED)) && shouldPublishCurrentRequestData(request)) {

String messageId = UUID.randomUUID().toString();

Expand All @@ -94,6 +101,9 @@ public void publishReportingData(HttpServletRequest request, HttpServletResponse
// publish api endpoint latency data
Map<String, Object> latencyData = generateLatencyDataMap(request, messageId);
CDSDataPublishingService.getCDSDataPublishingService().publishApiLatencyData(latencyData);
} else {
LOG.debug("Data publishing is disabled or the request is not an external request. Infosec data " +
"publishing skipped.");
}
}

Expand Down Expand Up @@ -245,4 +255,15 @@ private String extractClientId(HttpServletRequest request) {
public void destroy() {
}

/**
* Check whether data should be published for the current request.
*
* @return boolean
*/
public boolean shouldPublishCurrentRequestData(ServletRequest request) {

// If the request is internal traffic, no need to publish data
return expectedExternalTrafficHeaderValue.equalsIgnoreCase(
((HttpServletRequest) request).getHeader(externalTrafficHeaderName));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ public class CDSIdentityConstants {
public static final String CODE_RESPONSE_TYPE = "code";
public static final String JWT_RESPONSE_MODE = "jwt";
public static final String UNSUPPORTED_RESPONSE_TYPE_ERROR = "unsupported_response_type";
public static final String SESSION_DATA_KEY_PARAMETER = "sessionDataKey";

}
Loading

0 comments on commit f5a8866

Please sign in to comment.