Skip to content

Add support for global connection timeout and proxy configurations #13054

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
*/
package org.wso2.carbon.apimgt.api.model;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import java.util.HashMap;
import java.util.Map;

@JsonIgnoreProperties(ignoreUnknown = true)
public class EndpointSecurity {

private String uniqueIdentifier = null;
Expand Down Expand Up @@ -58,6 +61,10 @@ public class EndpointSecurity {

private ProxyConfigs proxyConfigs;

private TokenEndpointConnectionConfigType connectionTimeoutConfigType;

private TokenEndpointConnectionConfigType proxyConfigType;

public EndpointSecurity(EndpointSecurity endpointSecurity) {

this.uniqueIdentifier = endpointSecurity.uniqueIdentifier;
Expand All @@ -75,6 +82,8 @@ public EndpointSecurity(EndpointSecurity endpointSecurity) {
this.connectionRequestTimeoutDuration = endpointSecurity.connectionRequestTimeoutDuration;
this.socketTimeoutDuration = endpointSecurity.socketTimeoutDuration;
this.proxyConfigs = endpointSecurity.proxyConfigs;
this.connectionTimeoutConfigType = endpointSecurity.connectionTimeoutConfigType;
this.proxyConfigType = endpointSecurity.proxyConfigType;
}

public EndpointSecurity() {
Expand Down Expand Up @@ -251,13 +260,31 @@ public void setSocketTimeoutDuration(int socketTimeoutDuration) {
this.socketTimeoutDuration = socketTimeoutDuration;
}

public TokenEndpointConnectionConfigType getConnectionTimeoutConfigType() {
return connectionTimeoutConfigType;
}

public void setConnectionTimeoutConfigType(TokenEndpointConnectionConfigType connectionTimeoutConfigType) {
this.connectionTimeoutConfigType = connectionTimeoutConfigType;
}

public TokenEndpointConnectionConfigType getProxyConfigType() {
return proxyConfigType;
}

public void setProxyConfigType(TokenEndpointConnectionConfigType proxyConfigType) {
this.proxyConfigType = proxyConfigType;
}

@JsonIgnoreProperties(ignoreUnknown = true)
public static class ProxyConfigs {
private boolean proxyEnabled;
private String proxyHost;
private String proxyPort;
private String proxyProtocol;
private String proxyUsername;
private String proxyPassword;
private String proxyPasswordAlias;

public boolean isProxyEnabled() {
return proxyEnabled;
Expand Down Expand Up @@ -306,6 +333,14 @@ public String getProxyPassword() {
public void setProxyPassword(String proxyPassword) {
this.proxyPassword = proxyPassword;
}

public String getProxyPasswordAlias() {
return proxyPasswordAlias;
}

public void setProxyPasswordAlias(String proxyPasswordAlias) {
this.proxyPasswordAlias = proxyPasswordAlias;
}
}

@Override
Expand All @@ -329,6 +364,8 @@ public String toString() {
", connectionTimeoutDuration=" + connectionTimeoutDuration +
", connectionRequestTimeoutDuration=" + connectionRequestTimeoutDuration +
", socketTimeoutDuration=" + socketTimeoutDuration +
", connectionTimeoutConfigType=" + connectionTimeoutConfigType + '\'' +
", proxyConfigType=" + proxyConfigType + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com/).
*
* 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
*
* 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.carbon.apimgt.api.model;

public enum TokenEndpointConnectionConfigType {
GLOBAL,
ENDPOINT_SPECIFIC,
NONE
}
Original file line number Diff line number Diff line change
Expand Up @@ -1850,6 +1850,15 @@ private ConfigParameters() {
public static final String ENDPOINT_SECURITY_CLIENT_ID = "clientId";
public static final String ENDPOINT_SECURITY_CLIENT_SECRET = "clientSecret";
public static final String ENDPOINT_SECURITY_ENABLED = "enabled";
public static final String ENDPOINT_SECURITY_PROXY_PASSWORD = "proxyPassword";
public static final String CONNECTION_TIMEOUT_CONFIG_TYPE = "connectionTimeoutConfigType";
public static final String PROXY_CONFIG_TYPE = "proxyConfigType";
public static final String CONNECTION_TIMEOUT_DURATION = "connectionTimeoutDuration";
public static final String CONNECTION_REQUEST_TIMEOUT_DURATION = "connectionRequestTimeoutDuration";
public static final String SOCKET_TIMEOUT_DURATION = "socketTimeoutDuration";
public static final String PROXY_CONFIGS = "proxyConfigs";
public static final String PROXY_ENABLED = "proxyEnabled";
public static final String CONNECTION_TIMEOUT_DEFAULT = "-1";
public static final String ENDPOINT_SPECIFIC_CONFIG = "config";
public static final String ENDPOINT_CONFIG_ACTION_DURATION = "actionDuration";
public static final String ENDPOINT_TYPE_GRAPHQL = "graphql";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
import org.wso2.carbon.apimgt.api.model.Subscriber;
import org.wso2.carbon.apimgt.api.model.SwaggerData;
import org.wso2.carbon.apimgt.api.model.Tier;
import org.wso2.carbon.apimgt.api.model.TokenEndpointConnectionConfigType;
import org.wso2.carbon.apimgt.api.model.URITemplate;
import org.wso2.carbon.apimgt.api.model.Usage;
import org.wso2.carbon.apimgt.api.model.policy.APIPolicy;
Expand Down Expand Up @@ -5565,6 +5566,7 @@ public API getAPIbyUUID(String uuid, String organization) throws APIManagementEx
populateDefaultVersion(api);
populatePolicyTypeInAPI(api);
populateAPIPrimaryEndpointsMapping(api, uuid);
populateEndpointSecurityDefaults(api);
return api;
} else {
String msg = "Failed to get API. API artifact corresponding to artifactId " + uuid + " does not exist";
Expand All @@ -5585,6 +5587,85 @@ public API getAPIbyUUID(String uuid, String organization) throws APIManagementEx
}
}

/**
* Populates default values for endpoint security settings in the given API's endpoint configuration.
*
* @param api The {@link API} object whose endpoint security defaults need to be populated.
* @throws ParseException If there is an error while parsing the endpoint configuration JSON.
*/
private void populateEndpointSecurityDefaults(API api) throws ParseException {
String endpointConfig = api.getEndpointConfig();
if (StringUtils.isNotEmpty(endpointConfig)) {
JSONObject endpointConfigJson = (JSONObject) new JSONParser().parse(endpointConfig);
if (endpointConfigJson != null && endpointConfigJson.get(APIConstants.ENDPOINT_SECURITY) != null) {
JSONObject endpointSecurityJson = (JSONObject) endpointConfigJson.get(APIConstants.ENDPOINT_SECURITY);
if (endpointSecurityJson.get(APIConstants.ENDPOINT_SECURITY_PRODUCTION) != null) {
JSONObject productionEndpoint = (JSONObject) endpointSecurityJson.get(APIConstants.ENDPOINT_SECURITY_PRODUCTION);
setDefaultTokenEndpointConnectionConfigType(productionEndpoint);
}
if (endpointSecurityJson.get(APIConstants.ENDPOINT_SECURITY_SANDBOX) != null) {
JSONObject sandboxEndpoint = (JSONObject) endpointSecurityJson.get(APIConstants.ENDPOINT_SECURITY_SANDBOX);
setDefaultTokenEndpointConnectionConfigType(sandboxEndpoint);
}
}
api.setEndpointConfig(endpointConfigJson.toJSONString());
}
}

/**
* Sets the default token endpoint connection configuration type for the given endpoint.
*
* If the endpoint's security type is OAuth, this method ensures that the default values
* for connection timeout and proxy configurations types are properly assigned.
*
* @param endpoint The JSON object representing the endpoint configuration.
*/
private void setDefaultTokenEndpointConnectionConfigType(JSONObject endpoint) {
if (endpoint.get(APIConstants.ENDPOINT_SECURITY_TYPE) != null && endpoint.get(APIConstants
.ENDPOINT_SECURITY_TYPE).toString().equalsIgnoreCase(APIConstants.ENDPOINT_SECURITY_TYPE_OAUTH)) {
// Populate default values for connection timeout and proxy configurations
if (endpoint.get(APIConstants.CONNECTION_TIMEOUT_CONFIG_TYPE) == null) {
if (isDefaultConnectionTimeout(endpoint, APIConstants.CONNECTION_TIMEOUT_DURATION)
&& isDefaultConnectionTimeout(endpoint, APIConstants.CONNECTION_REQUEST_TIMEOUT_DURATION)
&& isDefaultConnectionTimeout(endpoint, APIConstants.SOCKET_TIMEOUT_DURATION)) {
// If all the connection timeouts are null or -1, use global config
endpoint.put(APIConstants.CONNECTION_TIMEOUT_CONFIG_TYPE,
TokenEndpointConnectionConfigType.GLOBAL.toString());
} else {
endpoint.put(APIConstants.CONNECTION_TIMEOUT_CONFIG_TYPE,
TokenEndpointConnectionConfigType.ENDPOINT_SPECIFIC.toString());
}
}
if (endpoint.get(APIConstants.PROXY_CONFIG_TYPE) == null) {
JSONObject proxyConfigs = (JSONObject) endpoint.get(APIConstants.PROXY_CONFIGS);
if (proxyConfigs != null && Boolean.TRUE.equals(proxyConfigs.get(APIConstants.PROXY_ENABLED))) {
// If proxy configurations are enabled, use endpoint specific config
endpoint.put(APIConstants.PROXY_CONFIG_TYPE, TokenEndpointConnectionConfigType
.ENDPOINT_SPECIFIC.toString());
} else {
endpoint.put(APIConstants.PROXY_CONFIG_TYPE, TokenEndpointConnectionConfigType.GLOBAL.toString());
}
}
}
}

/**
* Checks if the connection timeout value for the given endpoint is set to the default value.
*
* This method checks if the value for the specified connection timeout type in the provided
* endpoint is either null, or equals to the default connection timeout value.
*
* @param endpoint JSONObject representing the endpoint configuration.
* @param connectionTimeoutType String indicating the type of connection timeout to check.
* @return true if the connection timeout value is either null or set to the default value, otherwise false.
*/
private boolean isDefaultConnectionTimeout(JSONObject endpoint, String connectionTimeoutType) {
return endpoint.get(connectionTimeoutType) == null
|| APIConstants.CONNECTION_TIMEOUT_DEFAULT.equals(endpoint.get(connectionTimeoutType))
|| Integer.valueOf(APIConstants.CONNECTION_TIMEOUT_DEFAULT).equals(endpoint.get(connectionTimeoutType))
|| Long.valueOf(APIConstants.CONNECTION_TIMEOUT_DEFAULT).equals(endpoint.get(connectionTimeoutType));
}

/**
* Populates the AI configuration for the given API.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,13 @@ public static String retrieveOAuthPasswordAlias(String name, String version, Str
.concat(APIConstants.ENDPOINT_SECURITY_PASSWORD).concat("--").concat(type);
}

public static String retrieveOAuthProxyPasswordAlias(String name, String version, String type) {

return name.concat("--v").concat(version).concat("--")
.concat(APIConstants.ENDPOINT_SECURITY_TYPE_OAUTH).concat("--")
.concat(APIConstants.ENDPOINT_SECURITY_PROXY_PASSWORD).concat("--").concat(type);
}

public static String retrieveBasicAuthAlias(String name, String version, String type) {

return name.concat("--v").concat(version).concat("--").concat(type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1517,6 +1517,25 @@ private static void addCredentialsToList(String prefix, API api, GatewayAPIDTO g
gatewayAPIDTO.setCredentialsToBeAdd(addCredentialsToList(passwordDto,
gatewayAPIDTO.getCredentialsToBeAdd()));
}
if (endpointSecurity.has(APIConstants.PROXY_CONFIGS)) {
org.json.JSONObject proxyConfigs = (org.json.JSONObject) endpointSecurity.get(APIConstants
.PROXY_CONFIGS);
if (Boolean.TRUE.equals(proxyConfigs.get(APIConstants.PROXY_ENABLED))) {
String proxyPassword = (String) proxyConfigs.get(APIConstants.ENDPOINT_SECURITY_PROXY_PASSWORD);
CredentialDto proxyPasswordDto = new CredentialDto();
if (StringUtils.isNotEmpty(prefix)) {
proxyPasswordDto.setAlias(prefix.concat("--").concat(GatewayUtils
.retrieveOAuthProxyPasswordAlias(api.getId().getApiName(), api.getId().getVersion(),
type)));
} else {
proxyPasswordDto.setAlias(GatewayUtils.retrieveOAuthProxyPasswordAlias(api.getId().getApiName(),
api.getId().getVersion(), type));
}
proxyPasswordDto.setPassword(proxyPassword);
gatewayAPIDTO.setCredentialsToBeAdd(addCredentialsToList(proxyPasswordDto,
gatewayAPIDTO.getCredentialsToBeAdd()));
}
}
} else if (APIConstants.ENDPOINT_SECURITY_TYPE_BASIC.equalsIgnoreCase((String)
endpointSecurity.get(APIConstants.ENDPOINT_SECURITY_TYPE))) {
CredentialDto credentialDto = new CredentialDto();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
*/
package org.wso2.carbon.apimgt.rest.api.publisher.v1.common.template;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.wso2.carbon.apimgt.api.model.EndpointSecurity;

import java.io.Serializable;

/**
* This Class used for Endpoint Security Related data model.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class EndpointSecurityModel extends EndpointSecurity implements Serializable {

private String alias;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,24 +168,28 @@ private EndpointSecurityModel retrieveEndpointSecurityModel(EndpointSecurityMode
if (APIConstants.ENDPOINT_SECURITY_TYPE_OAUTH
.equalsIgnoreCase(endpointSecurityModel.getType())) {
if (StringUtils.isNotEmpty(prefix)) {
endpointSecurityModel.setUniqueIdentifier(prefix.concat("--")
.concat(GatewayUtils.retrieveUniqueIdentifier(apiId, type)));
endpointSecurityModel.setUniqueIdentifier(prefix.concat("--").concat(GatewayUtils
.retrieveUniqueIdentifier(apiId, type)));
endpointSecurityModel.setClientSecretAlias(prefix.concat("--").concat(GatewayUtils
.retrieveOauthClientSecretAlias(apiName, version, type)));
endpointSecurityModel.setPasswordAlias(prefix.concat("--").concat(GatewayUtils
.retrieveOAuthPasswordAlias(apiName, version, type)));
if (endpointSecurityModel.getProxyConfigs() != null && endpointSecurityModel.getProxyConfigs()
.isProxyEnabled()) {
endpointSecurityModel.getProxyConfigs().setProxyPasswordAlias(prefix.concat("--")
.concat(GatewayUtils.retrieveOAuthProxyPasswordAlias(apiName, version, type)));
}
} else {
endpointSecurityModel.setUniqueIdentifier(GatewayUtils.retrieveUniqueIdentifier(apiId, type));
}
if (StringUtils.isNotEmpty(prefix)) {
endpointSecurityModel.setClientSecretAlias(prefix.concat("--")
.concat(GatewayUtils.retrieveOauthClientSecretAlias(apiName, version, type)));
} else {
endpointSecurityModel.setClientSecretAlias(GatewayUtils.retrieveOauthClientSecretAlias(apiName,
version, type));
}
if (StringUtils.isNotEmpty(prefix)) {
endpointSecurityModel.setPasswordAlias(prefix.concat("--")
.concat(GatewayUtils.retrieveOAuthPasswordAlias(apiName, version, type)));
} else {
endpointSecurityModel.setPasswordAlias(GatewayUtils.retrieveOAuthPasswordAlias(apiName,
version, type));
endpointSecurityModel.setPasswordAlias(GatewayUtils.retrieveOAuthPasswordAlias(apiName, version,
type));
if (endpointSecurityModel.getProxyConfigs() != null && endpointSecurityModel.getProxyConfigs()
.isProxyEnabled()) {
endpointSecurityModel.getProxyConfigs().setProxyPasswordAlias(GatewayUtils
.retrieveOAuthProxyPasswordAlias(apiName, version, type));
}
}
}
if (StringUtils.isNotBlank(endpointSecurityModel.getUsername())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@
"apim.oauth_config.revoke_endpoint_context":"/revoke",
"apim.oauth_config.expires_in": "3600",
"apim.mediator_config.oauth.enable_retry_call_with_new_token": true,
"apim.mediator_config.oauth.connection_timeout_duration": "15000",
"apim.mediator_config.oauth.connection_request_timeout_duration": "15000",
"apim.mediator_config.oauth.socket_timeout_duration": "15000",
"apim.devportal.login_username_case_insensitive": true,
"apim.devportal.url": "https://localhost:${mgt.transport.https.port}/devportal",
"apim.devportal.display_url": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1787,6 +1787,9 @@
<ExpiresIn>{{apim.mediator_config.oauth.expires_in}}</ExpiresIn>
<!-- Enable/Disable retry API calls with new access token when the access token is invalid. Default is true. -->
<EnableRetryCallWithNewToken>{{apim.mediator_config.oauth.enable_retry_call_with_new_token}}</EnableRetryCallWithNewToken>
<ConnectionTimeoutDuration>{{apim.mediator_config.oauth.connection_timeout_duration}}</ConnectionTimeoutDuration>
<ConnectionRequestTimeoutDuration>{{apim.mediator_config.oauth.connection_request_timeout_duration}}</ConnectionRequestTimeoutDuration>
<SocketTimeoutDuration>{{apim.mediator_config.oauth.socket_timeout_duration}}</SocketTimeoutDuration>
</OAuth>
</MediatorConfigs>
{% endif %}
Expand Down
Loading