diff --git a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.common/src/main/java/org/wso2/carbon/identity/api/server/configs/common/ConfigsServiceHolder.java b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.common/src/main/java/org/wso2/carbon/identity/api/server/configs/common/ConfigsServiceHolder.java index 1309778855..76e236ab6d 100644 --- a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.common/src/main/java/org/wso2/carbon/identity/api/server/configs/common/ConfigsServiceHolder.java +++ b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.common/src/main/java/org/wso2/carbon/identity/api/server/configs/common/ConfigsServiceHolder.java @@ -27,6 +27,7 @@ import org.wso2.carbon.identity.cors.mgt.core.CORSManagementService; import org.wso2.carbon.identity.fraud.detection.core.service.FraudDetectionConfigsService; import org.wso2.carbon.identity.oauth.dcr.DCRConfigurationMgtService; +import org.wso2.carbon.identity.oauth2.agent.services.AgentConfigMgtService; import org.wso2.carbon.identity.oauth2.config.services.OAuth2OIDCConfigOrgUsageScopeMgtService; import org.wso2.carbon.identity.oauth2.impersonation.services.ImpersonationConfigMgtService; import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.JWTClientAuthenticatorMgtService; @@ -71,6 +72,12 @@ private static class ImpersonationConfigMgtServiceHolder { .getThreadLocalCarbonContext().getOSGiService(ImpersonationConfigMgtService.class, null); } + private static class AgentConfigMgtServiceHolder { + + static final AgentConfigMgtService SERVICE = (AgentConfigMgtService) PrivilegedCarbonContext + .getThreadLocalCarbonContext().getOSGiService(AgentConfigMgtService.class, null); + } + private static class DCRConfigurationMgtServiceHolder { static final DCRConfigurationMgtService SERVICE = (DCRConfigurationMgtService) PrivilegedCarbonContext @@ -176,6 +183,16 @@ public static ImpersonationConfigMgtService getImpersonationConfigMgtService() { return ImpersonationConfigMgtServiceHolder.SERVICE; } + /** + * Get Agent Config Mgt osgi service. + * + * @return AgentConfigMgtService + */ + public static AgentConfigMgtService getAgentConfigMgtService() { + + return AgentConfigMgtServiceHolder.SERVICE; + } + /** * Get DCRConfigurationMgtService osgi service. * diff --git a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.common/src/main/java/org/wso2/carbon/identity/api/server/configs/common/Constants.java b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.common/src/main/java/org/wso2/carbon/identity/api/server/configs/common/Constants.java index 5e4eb82d8e..905e1a477d 100644 --- a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.common/src/main/java/org/wso2/carbon/identity/api/server/configs/common/Constants.java +++ b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.common/src/main/java/org/wso2/carbon/identity/api/server/configs/common/Constants.java @@ -65,6 +65,11 @@ private Constants() { */ public static final String IMPERSONATION_CONFIG_ENABLE_EMAIL_NOTIFICATION = "/enableEmailNotification"; + /** + * PATCH operation path for Agent configuration. + */ + public static final String AGENT_CONFIG_AGENTS_EXTERNALLY_MANAGED = "/agentsExternallyManaged"; + /** * PATCH operation paths for DCR configuration. */ @@ -216,6 +221,15 @@ public enum ErrorMessage { ERROR_CODE_IMP_CONFIG_DELETE("65022", "Unable to delete Impersonation configuration.", "Server encountered an error while deleting the Impersonation configuration of %s."), + ERROR_CODE_AGENT_CONFIG_RETRIEVE("65036", + "Unable to retrieve Agent configuration.", + "Server encountered an error while retrieving the Agent configuration of %s."), + ERROR_CODE_AGENT_CONFIG_UPDATE("65037", + "Unable to update Agent configuration.", + "Server encountered an error while updating the Agent configuration of %s."), + ERROR_CODE_AGENT_CONFIG_DELETE("65038", + "Unable to delete Agent configuration.", + "Server encountered an error while deleting the Agent configuration of %s."), ERROR_CODE_FRAUD_DETECTION_CONFIG_RETRIEVE("65023", "Unable to retrieve Fraud Detection configuration.", diff --git a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/gen/java/org/wso2/carbon/identity/api/server/configs/v1/ConfigsApi.java b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/gen/java/org/wso2/carbon/identity/api/server/configs/v1/ConfigsApi.java index aa87c85a8a..e28dba8a60 100644 --- a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/gen/java/org/wso2/carbon/identity/api/server/configs/v1/ConfigsApi.java +++ b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/gen/java/org/wso2/carbon/identity/api/server/configs/v1/ConfigsApi.java @@ -34,6 +34,8 @@ import org.wso2.carbon.identity.api.server.configs.v1.model.DCRConfig; import org.wso2.carbon.identity.api.server.configs.v1.model.DCRPatch; import org.wso2.carbon.identity.api.server.configs.v1.model.Error; +import org.wso2.carbon.identity.api.server.configs.v1.model.AgentConfiguration; +import org.wso2.carbon.identity.api.server.configs.v1.model.AgentConfigPatch; import org.wso2.carbon.identity.api.server.configs.v1.model.FraudDetectionConfig; import org.wso2.carbon.identity.api.server.configs.v1.model.ImpersonationConfiguration; import org.wso2.carbon.identity.api.server.configs.v1.model.ImpersonationPatch; @@ -332,6 +334,30 @@ public Response getImpersonationConfiguration() { return delegate.getImpersonationConfiguration(); } + @Valid + @GET + @Path("/agent") + + @Produces({ "application/json" }) + @ApiOperation(value = "Retrieve the tenant agent configuration.", notes = "Retrieve the tenant agent configuration.", response = AgentConfiguration.class, authorizations = { + @Authorization(value = "BasicAuth"), + @Authorization(value = "OAuth2", scopes = { + + }) + }, tags={ "Agent Configurations", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Successful Response", response = AgentConfiguration.class), + @ApiResponse(code = 400, message = "Bad Request", response = Error.class), + @ApiResponse(code = 401, message = "Unauthorized", response = Void.class), + @ApiResponse(code = 403, message = "Forbidden", response = Void.class), + @ApiResponse(code = 404, message = "Not Found", response = Error.class), + @ApiResponse(code = 500, message = "Server Error", response = Error.class) + }) + public Response getAgentConfiguration() { + + return delegate.getAgentConfiguration(); + } + @Valid @GET @Path("/provisioning/inbound/scim") @@ -693,6 +719,30 @@ public Response patchImpersonationConfiguration(@ApiParam(value = "" ,required=t return delegate.patchImpersonationConfiguration(impersonationPatch ); } + @Valid + @PATCH + @Path("/agent") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @ApiOperation(value = "Patch the tenant agent configuration.", notes = "Patch the tenant agent configuration. A JSONPatch as defined by RFC 6902.", response = Void.class, authorizations = { + @Authorization(value = "BasicAuth"), + @Authorization(value = "OAuth2", scopes = { + + }) + }, tags={ "Agent Configurations", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Successful Response", response = Void.class), + @ApiResponse(code = 400, message = "Bad Request", response = Error.class), + @ApiResponse(code = 401, message = "Unauthorized", response = Void.class), + @ApiResponse(code = 403, message = "Forbidden", response = Void.class), + @ApiResponse(code = 404, message = "Not Found", response = Error.class), + @ApiResponse(code = 500, message = "Server Error", response = Error.class) + }) + public Response patchAgentConfiguration(@ApiParam(value = "" ,required=true) @Valid List agentConfigPatch) { + + return delegate.patchAgentConfiguration(agentConfigPatch ); + } + @Valid @PATCH @Path("/jwt-key-validator") @@ -834,6 +884,28 @@ public Response deleteImpersonationConfiguration() { return delegate.deleteImpersonationConfiguration(); } + @Valid + @DELETE + @Path("/agent") + + @Produces({ "application/json" }) + @ApiOperation(value = "Revert the tenant agent configuration.", notes = "Revert the tenant agent configuration. Scope (Permission) required:
* internal_config_update ", response = Void.class, authorizations = { + @Authorization(value = "BasicAuth"), + @Authorization(value = "OAuth2", scopes = { + + }) + }, tags={ "Agent Configurations", }) + @ApiResponses(value = { + @ApiResponse(code = 204, message = "Successful deletion", response = Void.class), + @ApiResponse(code = 401, message = "Unauthorized", response = Void.class), + @ApiResponse(code = 403, message = "Forbidden", response = Void.class), + @ApiResponse(code = 500, message = "Server Error", response = Error.class) + }) + public Response deleteAgentConfiguration() { + + return delegate.deleteAgentConfiguration(); + } + @Valid @PUT @Path("/fraud-detection") diff --git a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/gen/java/org/wso2/carbon/identity/api/server/configs/v1/ConfigsApiService.java b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/gen/java/org/wso2/carbon/identity/api/server/configs/v1/ConfigsApiService.java index 84d49386ee..999b2bd41d 100644 --- a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/gen/java/org/wso2/carbon/identity/api/server/configs/v1/ConfigsApiService.java +++ b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/gen/java/org/wso2/carbon/identity/api/server/configs/v1/ConfigsApiService.java @@ -22,6 +22,7 @@ import java.util.List; +import org.wso2.carbon.identity.api.server.configs.v1.model.AgentConfigPatch; import org.wso2.carbon.identity.api.server.configs.v1.model.CompatibilitySettings; import org.wso2.carbon.identity.api.server.configs.v1.model.CORSPatch; import org.wso2.carbon.identity.api.server.configs.v1.model.ImpersonationPatch; @@ -61,6 +62,8 @@ public interface ConfigsApiService { public Response getImpersonationConfiguration(); + public Response getAgentConfiguration(); + public Response getInboundScimConfigs(); public Response getIssuerUsageScopeConfig(); @@ -90,6 +93,8 @@ public interface ConfigsApiService { public Response patchImpersonationConfiguration(List impersonationPatch); + public Response patchAgentConfiguration(List agentConfigPatch); + public Response patchPrivatKeyJWTValidationConfiguration(List jwTKeyValidatorPatch); public Response patchDCRConfiguration(List patch); @@ -102,6 +107,8 @@ public interface ConfigsApiService { public Response deleteImpersonationConfiguration(); + public Response deleteAgentConfiguration(); + public Response updateFraudDetectionConfigs(FraudDetectionConfig fraudDetectionConfig); public Response updateInboundScimConfigs(ScimConfig scimConfig); diff --git a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/gen/java/org/wso2/carbon/identity/api/server/configs/v1/model/AgentConfigPatch.java b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/gen/java/org/wso2/carbon/identity/api/server/configs/v1/model/AgentConfigPatch.java new file mode 100644 index 0000000000..a357a0a82e --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/gen/java/org/wso2/carbon/identity/api/server/configs/v1/model/AgentConfigPatch.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2026, WSO2 LLC. (http://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.identity.api.server.configs.v1.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; + +public class AgentConfigPatch { + + +@XmlType(name="OperationEnum") +@XmlEnum(String.class) +public enum OperationEnum { + + @XmlEnumValue("ADD") ADD(String.valueOf("ADD")), @XmlEnumValue("REPLACE") REPLACE(String.valueOf("REPLACE")); + + + private String value; + + OperationEnum(String v) { + value = v; + } + + public String value() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + public static OperationEnum fromValue(String value) { + for (OperationEnum b : OperationEnum.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } +} + + private OperationEnum operation; + private String path; + private Boolean value; + + /** + * The operation to be performed. + **/ + public AgentConfigPatch operation(OperationEnum operation) { + + this.operation = operation; + return this; + } + + @ApiModelProperty(example = "REPLACE", required = true, value = "The operation to be performed.") + @JsonProperty("operation") + @Valid + @NotNull(message = "Property operation cannot be null.") + + public OperationEnum getOperation() { + return operation; + } + public void setOperation(OperationEnum operation) { + this.operation = operation; + } + + /** + * A JSON-Pointer + **/ + public AgentConfigPatch path(String path) { + + this.path = path; + return this; + } + + @ApiModelProperty(example = "/agentsExternallyManaged", required = true, value = "A JSON-Pointer") + @JsonProperty("path") + @Valid + @NotNull(message = "Property path cannot be null.") + + public String getPath() { + return path; + } + public void setPath(String path) { + this.path = path; + } + + /** + * The value to be used within the operations. + **/ + public AgentConfigPatch value(Boolean value) { + + this.value = value; + return this; + } + + @ApiModelProperty(example = "true", required = true, value = "The value to be used within the operations.") + @JsonProperty("value") + @Valid + @NotNull(message = "Property value cannot be null.") + + public Boolean getValue() { + return value; + } + public void setValue(Boolean value) { + this.value = value; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AgentConfigPatch agentConfigPatch = (AgentConfigPatch) o; + return Objects.equals(this.operation, agentConfigPatch.operation) && + Objects.equals(this.path, agentConfigPatch.path) && + Objects.equals(this.value, agentConfigPatch.value); + } + + @Override + public int hashCode() { + return Objects.hash(operation, path, value); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class AgentConfigPatch {\n"); + + sb.append(" operation: ").append(toIndentedString(operation)).append("\n"); + sb.append(" path: ").append(toIndentedString(path)).append("\n"); + sb.append(" value: ").append(toIndentedString(value)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} diff --git a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/gen/java/org/wso2/carbon/identity/api/server/configs/v1/model/AgentConfiguration.java b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/gen/java/org/wso2/carbon/identity/api/server/configs/v1/model/AgentConfiguration.java new file mode 100644 index 0000000000..6f7c0c9be7 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/gen/java/org/wso2/carbon/identity/api/server/configs/v1/model/AgentConfiguration.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2026, WSO2 LLC. (http://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.identity.api.server.configs.v1.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; + +public class AgentConfiguration { + + private Boolean agentsExternallyManaged; + + /** + * If true, the tenant's agents are managed in an external system and the requested actor is not validated against the local agent user store. + **/ + public AgentConfiguration agentsExternallyManaged(Boolean agentsExternallyManaged) { + + this.agentsExternallyManaged = agentsExternallyManaged; + return this; + } + + @ApiModelProperty(example = "false", value = "If true, the tenant's agents are managed in an external system and the requested actor is not validated against the local agent user store.") + @JsonProperty("agentsExternallyManaged") + @Valid + public Boolean getAgentsExternallyManaged() { + return agentsExternallyManaged; + } + public void setAgentsExternallyManaged(Boolean agentsExternallyManaged) { + this.agentsExternallyManaged = agentsExternallyManaged; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AgentConfiguration agentConfiguration = (AgentConfiguration) o; + return Objects.equals(this.agentsExternallyManaged, agentConfiguration.agentsExternallyManaged); + } + + @Override + public int hashCode() { + return Objects.hash(agentsExternallyManaged); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class AgentConfiguration {\n"); + + sb.append(" agentsExternallyManaged: ").append(toIndentedString(agentsExternallyManaged)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} diff --git a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/java/org/wso2/carbon/identity/api/server/configs/v1/core/ServerConfigManagementService.java b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/java/org/wso2/carbon/identity/api/server/configs/v1/core/ServerConfigManagementService.java index 863a893175..4b5d6f0109 100644 --- a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/java/org/wso2/carbon/identity/api/server/configs/v1/core/ServerConfigManagementService.java +++ b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/java/org/wso2/carbon/identity/api/server/configs/v1/core/ServerConfigManagementService.java @@ -40,6 +40,8 @@ import org.wso2.carbon.identity.api.server.configs.v1.function.CompatibilitySettingUtil; import org.wso2.carbon.identity.api.server.configs.v1.function.DCRConnectorUtil; import org.wso2.carbon.identity.api.server.configs.v1.function.JWTConnectorUtil; +import org.wso2.carbon.identity.api.server.configs.v1.model.AgentConfigPatch; +import org.wso2.carbon.identity.api.server.configs.v1.model.AgentConfiguration; import org.wso2.carbon.identity.api.server.configs.v1.model.ApplicationObject; import org.wso2.carbon.identity.api.server.configs.v1.model.AuthenticationType; import org.wso2.carbon.identity.api.server.configs.v1.model.Authenticator; @@ -112,6 +114,11 @@ import org.wso2.carbon.identity.fraud.detection.core.service.FraudDetectionConfigsService; import org.wso2.carbon.identity.oauth.dcr.DCRConfigurationMgtService; import org.wso2.carbon.identity.oauth.dcr.exception.DCRMException; +import org.wso2.carbon.identity.oauth2.agent.exceptions.AgentConfigMgtClientException; +import org.wso2.carbon.identity.oauth2.agent.exceptions.AgentConfigMgtException; +import org.wso2.carbon.identity.oauth2.agent.exceptions.AgentConfigMgtServerException; +import org.wso2.carbon.identity.oauth2.agent.models.AgentConfig; +import org.wso2.carbon.identity.oauth2.agent.services.AgentConfigMgtService; import org.wso2.carbon.identity.oauth2.config.exceptions.OAuth2OIDCConfigOrgUsageScopeMgtClientException; import org.wso2.carbon.identity.oauth2.config.exceptions.OAuth2OIDCConfigOrgUsageScopeMgtException; import org.wso2.carbon.identity.oauth2.config.models.IssuerUsageScopeConfig; @@ -172,6 +179,7 @@ public class ServerConfigManagementService { private final CORSManagementService corsManagementService; private final RemoteLoggingConfigService remoteLoggingConfigService; private final ImpersonationConfigMgtService impersonationConfigMgtService; + private final AgentConfigMgtService agentConfigMgtService; private final JWTClientAuthenticatorMgtService jwtClientAuthenticatorMgtService; private final DCRConfigurationMgtService dcrConfigurationMgtService; private final OAuth2OIDCConfigOrgUsageScopeMgtService oauth2OIDCConfigOrgUsageScopeMgtService; @@ -184,6 +192,7 @@ public ServerConfigManagementService(ApplicationManagementService applicationMan CORSManagementService corsManagementService, RemoteLoggingConfigService remoteLoggingConfigService, ImpersonationConfigMgtService impersonationConfigMgtService, + AgentConfigMgtService agentConfigMgtService, DCRConfigurationMgtService dcrConfigurationMgtService, JWTClientAuthenticatorMgtService jwtClientAuthenticatorMgtService, FraudDetectionConfigsService fraudDetectionConfigsService, @@ -196,6 +205,7 @@ public ServerConfigManagementService(ApplicationManagementService applicationMan this.corsManagementService = corsManagementService; this.remoteLoggingConfigService = remoteLoggingConfigService; this.impersonationConfigMgtService = impersonationConfigMgtService; + this.agentConfigMgtService = agentConfigMgtService; this.dcrConfigurationMgtService = dcrConfigurationMgtService; this.jwtClientAuthenticatorMgtService = jwtClientAuthenticatorMgtService; this.fraudDetectionConfigsService = fraudDetectionConfigsService; @@ -520,6 +530,86 @@ public void deleteImpersonationConfiguration() { } } + /** + * Retrieves the agent configuration for the current tenant domain. + * + * @return AgentConfiguration The current agent configuration. + * @throws AgentConfigMgtException If there is an error retrieving the agent configuration. + */ + public AgentConfiguration getAgentConfiguration() { + + String tenantDomain = ContextLoader.getTenantDomainFromContext(); + AgentConfiguration agentConfiguration = new AgentConfiguration(); + try { + AgentConfig agentConfig = agentConfigMgtService.getAgentConfig(tenantDomain); + return agentConfiguration.agentsExternallyManaged(agentConfig.isAgentsExternallyManaged()); + } catch (AgentConfigMgtException e) { + throw handleAgentConfigException(e, Constants.ErrorMessage.ERROR_CODE_AGENT_CONFIG_RETRIEVE, tenantDomain); + } + } + + /** + * Applies patch operations to the agent configuration for the current tenant domain. + * + * @param agentConfigPatchList List of patch operations to apply. + * @throws AgentConfigMgtException If there is an error updating the agent configuration. + */ + public void patchAgentConfiguration(List agentConfigPatchList) { + + if (CollectionUtils.isEmpty(agentConfigPatchList)) { + return; + } + + String tenantDomain = ContextLoader.getTenantDomainFromContext(); + AgentConfig agentConfig; + try { + agentConfig = agentConfigMgtService.getAgentConfig(tenantDomain); + } catch (AgentConfigMgtException e) { + throw handleAgentConfigException(e, Constants.ErrorMessage.ERROR_CODE_AGENT_CONFIG_RETRIEVE, tenantDomain); + } + + try { + for (AgentConfigPatch agentConfigPatch : agentConfigPatchList) { + String path = agentConfigPatch.getPath(); + AgentConfigPatch.OperationEnum operation = agentConfigPatch.getOperation(); + boolean value = agentConfigPatch.getValue(); + + // Support only 'REPLACE' and 'ADD' patch operations on the externally-managed flag. + if (operation == AgentConfigPatch.OperationEnum.REPLACE + || operation == AgentConfigPatch.OperationEnum.ADD) { + if (path.matches(Constants.AGENT_CONFIG_AGENTS_EXTERNALLY_MANAGED)) { + agentConfig.setAgentsExternallyManaged(value); + } else { + throw handleException(Response.Status.BAD_REQUEST, Constants.ErrorMessage + .ERROR_CODE_INVALID_INPUT, "Unsupported patch operation"); + } + } else { + throw handleException(Response.Status.BAD_REQUEST, Constants.ErrorMessage + .ERROR_CODE_INVALID_INPUT, "Unsupported patch operation"); + } + } + + agentConfigMgtService.setAgentConfig(agentConfig, tenantDomain); + } catch (AgentConfigMgtException e) { + throw handleAgentConfigException(e, Constants.ErrorMessage.ERROR_CODE_AGENT_CONFIG_UPDATE, tenantDomain); + } + } + + /** + * Deletes the agent configuration for the current tenant domain. + * + * @throws AgentConfigMgtException If there is an error deleting the agent configuration. + */ + public void deleteAgentConfiguration() { + + String tenantDomain = ContextLoader.getTenantDomainFromContext(); + try { + agentConfigMgtService.deleteAgentConfig(tenantDomain); + } catch (AgentConfigMgtException e) { + throw handleAgentConfigException(e, Constants.ErrorMessage.ERROR_CODE_AGENT_CONFIG_DELETE, tenantDomain); + } + } + /** * Get the CORS config for a tenant. */ @@ -1457,6 +1547,43 @@ private APIError handleImpersonationConfigException(ImpersonationConfigMgtExcept return new APIError(status, errorResponse); } + private APIError handleAgentConfigException(AgentConfigMgtException e, + Constants.ErrorMessage errorEnum, String data) { + + ErrorResponse errorResponse; + + Response.Status status; + + if (e instanceof AgentConfigMgtClientException) { + errorResponse = getErrorBuilder(errorEnum, data).build(log, e.getMessage()); + if (e.getErrorCode() != null) { + String errorCode = e.getErrorCode(); + errorCode = + errorCode.contains(org.wso2.carbon.identity.api.server.common.Constants.ERROR_CODE_DELIMITER) ? + errorCode : Constants.CONFIG_ERROR_PREFIX + errorCode; + errorResponse.setCode(errorCode); + } + errorResponse.setDescription(e.getMessage()); + status = Response.Status.BAD_REQUEST; + } else if (e instanceof AgentConfigMgtServerException) { + errorResponse = getErrorBuilder(errorEnum, data).build(log, e, errorEnum.description()); + if (e.getErrorCode() != null) { + String errorCode = e.getErrorCode(); + errorCode = + errorCode.contains(org.wso2.carbon.identity.api.server.common.Constants.ERROR_CODE_DELIMITER) ? + errorCode : Constants.CONFIG_ERROR_PREFIX + errorCode; + errorResponse.setCode(errorCode); + } + errorResponse.setDescription(e.getMessage()); + status = Response.Status.INTERNAL_SERVER_ERROR; + } else { + errorResponse = getErrorBuilder(errorEnum, data).build(log, e, errorEnum.description()); + status = Response.Status.INTERNAL_SERVER_ERROR; + } + return new APIError(status, errorResponse); + } + + /** * Handle exceptions generated in API. * diff --git a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/java/org/wso2/carbon/identity/api/server/configs/v1/factories/ServerConfigManagementServiceFactory.java b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/java/org/wso2/carbon/identity/api/server/configs/v1/factories/ServerConfigManagementServiceFactory.java index df4b6c514e..765be08778 100644 --- a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/java/org/wso2/carbon/identity/api/server/configs/v1/factories/ServerConfigManagementServiceFactory.java +++ b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/java/org/wso2/carbon/identity/api/server/configs/v1/factories/ServerConfigManagementServiceFactory.java @@ -7,6 +7,7 @@ import org.wso2.carbon.identity.cors.mgt.core.CORSManagementService; import org.wso2.carbon.identity.fraud.detection.core.service.FraudDetectionConfigsService; import org.wso2.carbon.identity.oauth.dcr.DCRConfigurationMgtService; +import org.wso2.carbon.identity.oauth2.agent.services.AgentConfigMgtService; import org.wso2.carbon.identity.oauth2.config.services.OAuth2OIDCConfigOrgUsageScopeMgtService; import org.wso2.carbon.identity.oauth2.impersonation.services.ImpersonationConfigMgtService; import org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt.core.JWTClientAuthenticatorMgtService; @@ -30,6 +31,7 @@ public class ServerConfigManagementServiceFactory { RemoteLoggingConfigService remoteLoggingConfigService = ConfigsServiceHolder.getRemoteLoggingConfigService(); ImpersonationConfigMgtService impersonationConfigMgtService = ConfigsServiceHolder .getImpersonationConfigMgtService(); + AgentConfigMgtService agentConfigMgtService = ConfigsServiceHolder.getAgentConfigMgtService(); JWTClientAuthenticatorMgtService jwtClientAuthenticatorMgtService = ConfigsServiceHolder .getJWTClientAuthenticatorMgtService(); DCRConfigurationMgtService dcrConfigurationMgtService = ConfigsServiceHolder.getDcrConfigurationMgtService(); @@ -60,6 +62,10 @@ public class ServerConfigManagementServiceFactory { throw new IllegalStateException("ImpersonationConfigMgtService is not available from OSGi context."); } + if (agentConfigMgtService == null) { + throw new IllegalStateException("AgentConfigMgtService is not available from OSGi context."); + } + if (jwtClientAuthenticatorMgtService == null) { throw new IllegalStateException("JWTClientAuthenticatorMgtService is not available from OSGi context."); } @@ -85,6 +91,7 @@ public class ServerConfigManagementServiceFactory { corsManagementService, remoteLoggingConfigService, impersonationConfigMgtService, + agentConfigMgtService, dcrConfigurationMgtService, jwtClientAuthenticatorMgtService, fraudDetectionConfigsService, diff --git a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/java/org/wso2/carbon/identity/api/server/configs/v1/impl/ConfigsApiServiceImpl.java b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/java/org/wso2/carbon/identity/api/server/configs/v1/impl/ConfigsApiServiceImpl.java index c51ef12368..8b73a9372e 100644 --- a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/java/org/wso2/carbon/identity/api/server/configs/v1/impl/ConfigsApiServiceImpl.java +++ b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/java/org/wso2/carbon/identity/api/server/configs/v1/impl/ConfigsApiServiceImpl.java @@ -21,6 +21,7 @@ import org.wso2.carbon.identity.api.server.configs.v1.ConfigsApiService; import org.wso2.carbon.identity.api.server.configs.v1.core.ServerConfigManagementService; import org.wso2.carbon.identity.api.server.configs.v1.factories.ServerConfigManagementServiceFactory; +import org.wso2.carbon.identity.api.server.configs.v1.model.AgentConfigPatch; import org.wso2.carbon.identity.api.server.configs.v1.model.ApplicationObject; import org.wso2.carbon.identity.api.server.configs.v1.model.CORSPatch; import org.wso2.carbon.identity.api.server.configs.v1.model.CompatibilitySettings; @@ -88,6 +89,12 @@ public Response getImpersonationConfiguration() { return Response.ok().entity(configManagementService.getImpersonationConfiguration()).build(); } + @Override + public Response getAgentConfiguration() { + + return Response.ok().entity(configManagementService.getAgentConfiguration()).build(); + } + @Override public Response getInboundScimConfigs() { @@ -223,6 +230,20 @@ public Response deleteImpersonationConfiguration() { return Response.noContent().build(); } + @Override + public Response patchAgentConfiguration(List agentConfigPatch) { + + configManagementService.patchAgentConfiguration(agentConfigPatch); + return Response.ok().build(); + } + + @Override + public Response deleteAgentConfiguration() { + + configManagementService.deleteAgentConfiguration(); + return Response.noContent().build(); + } + @Override public Response updateInboundScimConfigs(ScimConfig scimConfig) { diff --git a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/resources/configs.yaml b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/resources/configs.yaml index 348e6e3476..79d41a9615 100644 --- a/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/resources/configs.yaml +++ b/components/org.wso2.carbon.identity.api.server.configs/org.wso2.carbon.identity.api.server.configs.v1/src/main/resources/configs.yaml @@ -578,6 +578,101 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' + /configs/agent: + get: + tags: + - Agent Configurations + summary: Retrieve the tenant agent configuration. + operationId: getAgentConfiguration + description: Retrieve the tenant agent configuration. + responses: + '200': + description: Successful Response + content: + application/json: + schema: + $ref: '#/components/schemas/AgentConfiguration' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + patch: + tags: + - Agent Configurations + summary: Patch the tenant agent configuration. + operationId: patchAgentConfiguration + description: Patch the tenant agent configuration. A JSONPatch as defined by RFC 6902. + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AgentConfigPatchRequest' + required: true + responses: + '200': + description: Successful Response + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: + tags: + - Agent Configurations + summary: Revert the tenant agent configuration. + operationId: deleteAgentConfiguration + description: | + Revert the tenant agent configuration. + Scope (Permission) required:
+ * internal_config_update + responses: + '204': + description: Successful deletion + '401': + description: Unauthorized + '403': + description: Forbidden + '500': + description: Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' /configs/home-realm-identifiers: get: tags: @@ -2182,6 +2277,39 @@ components: type: boolean description: The value to be used within the operations. example: false + AgentConfiguration: + type: object + properties: + agentsExternallyManaged: + type: boolean + description: If true, the tenant's agents are managed in an external system and the requested_actor is not validated against the local agent store in authorization. + example: false + AgentConfigPatchRequest: + type: array + items: + $ref: '#/components/schemas/AgentConfigPatch' + AgentConfigPatch: + type: object + required: + - operation + - path + - value + properties: + operation: + type: string + description: The operation to be performed. + enum: + - ADD + - REPLACE + example: REPLACE + path: + type: string + description: A JSON-Pointer + example: '/agentsExternallyManaged' + value: + type: boolean + description: The value to be used within the operations. + example: true HomeRealmIdentifiers: type: array description: The list of home realm identifiers. diff --git a/pom.xml b/pom.xml index ebbe4502c6..ae6b6d710d 100644 --- a/pom.xml +++ b/pom.xml @@ -1118,7 +1118,7 @@ **/gen/**/* 1.12.4 5.10.1 - 7.5.46 + 7.5.59 5.11.51 1.1.19 1.9.4