Skip to content
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

DCR tenant-wise configurations : Get and Patch endpoint implementation #583

Merged
merged 25 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4e02089
DCR Server Configuration Get and Patch impl
anjuchamantha Jan 16, 2024
0c3a8ee
Merge branch 'master' into dcr-tenant-wise
anjuchamantha Jan 16, 2024
36ee281
DCR Server Configuration Bug Fix
anjuchamantha Jan 18, 2024
caf4d81
Add DCR configs to /configs endpoint
anjuchamantha Jan 23, 2024
6ab8d38
Add oauth.dcr version
anjuchamantha Jan 24, 2024
36ea2f1
Update licence headers
anjuchamantha Jan 29, 2024
606f5f7
DCR Config Bug fix
anjuchamantha Feb 1, 2024
a922694
Merge branch 'master' into dcr-tenant-wise
anjuchamantha Feb 8, 2024
414c974
Add mandateSSA dcr config
anjuchamantha Feb 13, 2024
e4b5fa4
Bug fix in DCR configurations
anjuchamantha Feb 15, 2024
8ac3dde
Change DCR configuration name
anjuchamantha Feb 16, 2024
8f9a577
Throw error for SSA mandation without SSA JWKS url
anjuchamantha Feb 16, 2024
8555ef5
Merge branch 'master' into dcr-tenant-wise
anjuchamantha Mar 28, 2024
18379bf
Change DCR Configuration Error Codes
anjuchamantha Apr 13, 2024
6a245e3
Add javadoc comments for DCR public methods
anjuchamantha Apr 13, 2024
4e9647f
Refactoring DCRMgtOGSiServiceFactory class
anjuchamantha Apr 13, 2024
f08d4c5
Send proper error msg in DCR Config
anjuchamantha Apr 15, 2024
c2837a5
Remove method naming inconsistency in DCR Config
anjuchamantha Apr 15, 2024
6ba0edc
Refactoring code in ConfigsApi
anjuchamantha Apr 15, 2024
5b78c93
Merge branch 'master' into dcr-tenant-wise
anjuchamantha May 7, 2024
d293984
Bump inbound oauth version
anjuchamantha May 10, 2024
2f127c3
[DCR] Refactor Log variable
anjuchamantha May 13, 2024
92937d8
[DCR] Remove graceful checking for DCR OSGI service
anjuchamantha May 14, 2024
5a28f08
[DCR] Remove DCRConfigException
anjuchamantha May 14, 2024
d700118
[DCR] Refactor: adding new line
anjuchamantha May 14, 2024
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 @@ -62,6 +62,11 @@
<artifactId>org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.inbound.auth.oauth2</groupId>
<artifactId>org.wso2.carbon.identity.oauth.dcr</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.commons</groupId>
<artifactId>org.wso2.carbon.logging.service</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ private Constants() {
*/
public static final String PRIVATE_KEY_JWT_VALIDATION_CONFIG_TOKEN_REUSE = "/enableTokenReuse";

/**
* PATCH operation paths for DCR configuration.
*/
public static final String DCR_CONFIG_ENABLE_FAPI_ENFORCEMENT = "/enableFapiEnforcement";
public static final String DCR_CONFIG_SSA_JWKS = "/ssaJwks";
public static final String DCR_CONFIG_CLIENT_AUTHENTICATION_REQUIRED = "/clientAuthenticationRequired";

/**
* SAML2 metadata endpoint uri path.
*/
Expand Down Expand Up @@ -125,7 +132,7 @@ public enum ErrorMessage {
"Unable to update remote logging configs.",
"Server encountered an " +
"error while updating the remote logging configs."),
ERROR_CODE_ERROR_GETTING_REMOTE_LOGGING_CONFIGS("65008",
ERROR_CODE_ERROR_GETTING_REMOTE_LOGGING_CONFIGS("65017",
anjuchamantha marked this conversation as resolved.
Show resolved Hide resolved
"Unable to get remote logging configs.",
"Server encountered an " +
"error while getting the remote logging configs."),
Expand All @@ -142,6 +149,22 @@ public enum ErrorMessage {
"Resource not found.",
"Unable to find a resource matching the provided log type %s."),

/**
* DCR Configuration errors.
*/
ERROR_DCR_CONFIG_SERVICE_NOT_FOUND("60509",
anjuchamantha marked this conversation as resolved.
Show resolved Hide resolved
"DCR Management Service not found.",
"DCR Management Service is unavailable at the moment."),

ERROR_CODE_DCR_CONFIG_RETRIEVE("65018",
"Unable to retrieve DCR configuration.",
"Server encountered an error while retrieving the " +
"DCR configuration."),

ERROR_CODE_DCR_CONFIG_UPDATE("65019",
"Unable to update DCR configuration.",
"Server encountered an error while updating the DCR configuration."),

/**
* Inbound auth config error messages.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2024, 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.common.factory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.oauth.dcr.DCRConfigurationMgtService;

/**
* Since this factory produces DCRConfigurationMgtService connector service, there is a possibility that said
* connector not available in the distribution.
* So rather than designing as Factory Beans this class designed as Singleton.
*/
public class DCRMgtOGSiServiceFactory {

private static DCRConfigurationMgtService dcrConfigurationMgtService = null;
private static final Log log = LogFactory.getLog(DCRMgtOGSiServiceFactory.class);
anjuchamantha marked this conversation as resolved.
Show resolved Hide resolved


/**
* This method return the instance if the OSGi service exists.
* Else throw Null pointer Exception. We handle the exception gracefully.
*
* @return DCRConfigurationMgtService
*/
public static DCRConfigurationMgtService getInstance() {
anjuchamantha marked this conversation as resolved.
Show resolved Hide resolved

if (dcrConfigurationMgtService == null) {
/* Try catch statement is included due to a NullPointerException which occurs at the server startup and
runtime when the DCRConfigurationMgtService is not available in the product. */

try {
// Call class for name to check the class is available in the run time.
// This method will call only once at the first api call.
Class.forName("org.wso2.carbon.identity.oauth.dcr.DCRConfigurationMgtService");
DCRConfigurationMgtService taskOperationService
= (DCRConfigurationMgtService) PrivilegedCarbonContext.
getThreadLocalCarbonContext().getOSGiService
(DCRConfigurationMgtService.class, null);
if (taskOperationService != null) {
dcrConfigurationMgtService = taskOperationService;
}

} catch (NullPointerException | ClassNotFoundException e) {
/* Catch block without implementation so that the DCRConfigurationMgtService will be set to null
in-turn helps in validating the rest API requests. */
if (log.isDebugEnabled()) {
log.debug("Unable to find the DCRConfigurationMgtService. " +
"DCRConfigurationMgtService is not available in the server.");
}
}
}

return dcrConfigurationMgtService;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@
<artifactId>org.wso2.carbon.identity.oauth2.token.handler.clientauth.jwt</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.inbound.auth.oauth2</groupId>
<artifactId>org.wso2.carbon.identity.oauth.dcr</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.commons</groupId>
<artifactId>org.wso2.carbon.logging.service</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import org.wso2.carbon.identity.api.server.configs.v1.model.AuthenticatorListItem;
import org.wso2.carbon.identity.api.server.configs.v1.model.CORSConfig;
import org.wso2.carbon.identity.api.server.configs.v1.model.CORSPatch;
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.InboundAuthPassiveSTSConfig;
import org.wso2.carbon.identity.api.server.configs.v1.model.InboundAuthSAML2Config;
Expand All @@ -47,6 +49,7 @@
import javax.ws.rs.*;
import javax.ws.rs.core.Response;
import io.swagger.annotations.*;
import org.wso2.carbon.identity.api.server.configs.v1.model.Error;
anjuchamantha marked this conversation as resolved.
Show resolved Hide resolved

import javax.validation.constraints.*;

Expand Down Expand Up @@ -226,6 +229,30 @@ public Response getPrivatKeyJWTValidationConfiguration() {
return delegate.getPrivatKeyJWTValidationConfiguration();
}

@Valid
@GET
@Path("/dcr")

@Produces({ "application/json" })
@ApiOperation(value = "Retrieve the tenant dcr configuration.", notes = "Retrieve the tenant dcr configuration.", response = DCRConfig.class, authorizations = {
@Authorization(value = "BasicAuth"),
@Authorization(value = "OAuth2", scopes = {

})
}, tags={ "DCR Configurations", })
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successful Response", response = DCRConfig.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 getDCRConfiguration() {

return delegate.getDCRConfiguration();
}

@Valid
@GET
@Path("/remote-logging/{log-type}")
Expand Down Expand Up @@ -443,6 +470,30 @@ public Response patchPrivatKeyJWTValidationConfiguration(@ApiParam(value = "" ,r
return delegate.patchPrivatKeyJWTValidationConfiguration(jwTKeyValidatorPatch );
}

@Valid
@PATCH
@Path("/dcr")
@Consumes({ "application/json" })
@Produces({ "application/json" })
@ApiOperation(value = "Patch the tenant dcr configuration.", notes = "Patch the tenant dcr authentication configuration. A JSONPatch as defined by RFC 6902.", response = Void.class, authorizations = {
@Authorization(value = "BasicAuth"),
@Authorization(value = "OAuth2", scopes = {

})
}, tags={ "DCR 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 patchDCRConfiguration(@ApiParam(value = "" ,required=true) @Valid List<DCRPatch> dcrPatch) {

return delegate.patchDCRConfiguration(dcrPatch );
}

@Valid
@DELETE
@Path("/remote-logging/{log-type}")
Expand Down Expand Up @@ -526,7 +577,7 @@ public Response updateInboundScimConfigs(@ApiParam(value = "" ,required=true) @V

})
}, tags={ "Inbound Authentication Configurations", })
@ApiResponses(value = {
@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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public interface ConfigsApiService {
public Response getPassiveSTSInboundAuthConfig();

public Response getPrivatKeyJWTValidationConfiguration();
public Response getDCRConfiguration();

public Response getRemoteLoggingConfig(String logType);

Expand All @@ -78,6 +79,8 @@ public interface ConfigsApiService {

public Response patchPrivatKeyJWTValidationConfiguration(List<JWTKeyValidatorPatch> jwTKeyValidatorPatch);

public Response patchDCRConfiguration(List<DCRPatch> patch);

public Response restoreServerRemoteLoggingConfiguration(String logType);

public Response restoreServerRemoteLoggingConfigurations();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Copyright (c) 2024, 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 io.swagger.annotations.ApiModelProperty;
import java.util.Objects;
import javax.validation.Valid;

public class DCRConfig {

private Boolean clientAuthenticationRequired;
private String ssaJwks;
private Boolean enableFapiEnforcement;

/**
* If false, the client authentication is not required for the DCR request, otherwise, the configured authentication mechanism will be used.
**/
public DCRConfig clientAuthenticationRequired(Boolean clientAuthenticationRequired) {

this.clientAuthenticationRequired = clientAuthenticationRequired;
return this;
}

@ApiModelProperty(example = "false", value = "If false, the client authentication is not required for the DCR request, otherwise, the configured authentication mechanism will be used.")
@JsonProperty("clientAuthenticationRequired")
@Valid
public Boolean getClientAuthenticationRequired() {

return clientAuthenticationRequired;
}
public void setClientAuthenticationRequired(Boolean clientAuthenticationRequired) {

this.clientAuthenticationRequired = clientAuthenticationRequired;
}

/**
* The JWKS endpoint to validate the SSA.
**/
public DCRConfig ssaJwks(String ssaJwks) {

this.ssaJwks = ssaJwks;
return this;
}

@ApiModelProperty(example = "https://keystore.openbankingtest.org.uk/0015800001HQQrZAAX/oQ4KoaavpOuoE7rvQsZEOV.jwks", value = "The JWKS endpoint to validate the SSA.")
@JsonProperty("ssaJwks")
@Valid
public String getSsaJwks() {

return ssaJwks;
}
public void setSsaJwks(String ssaJwks) {

this.ssaJwks = ssaJwks;
}

/**
* If true, the FAPI security profile will be enforced for the DCR request.
**/
public DCRConfig enableFapiEnforcement(Boolean enableFapiEnforcement) {

this.enableFapiEnforcement = enableFapiEnforcement;
return this;
}

@ApiModelProperty(example = "true", value = "If true, the FAPI security profile will be enforced for the DCR request.")
@JsonProperty("enableFapiEnforcement")
@Valid
public Boolean getEnableFapiEnforcement() {

return enableFapiEnforcement;
}
public void setEnableFapiEnforcement(Boolean enableFapiEnforcement) {

this.enableFapiEnforcement = enableFapiEnforcement;
}



@Override
public boolean equals(java.lang.Object o) {

if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
DCRConfig dcRConfig = (DCRConfig) o;
return Objects.equals(this.clientAuthenticationRequired, dcRConfig.clientAuthenticationRequired) &&
Objects.equals(this.ssaJwks, dcRConfig.ssaJwks) &&
Objects.equals(this.enableFapiEnforcement, dcRConfig.enableFapiEnforcement);
}

@Override
public int hashCode() {

return Objects.hash(clientAuthenticationRequired, ssaJwks, enableFapiEnforcement);
}

@Override
public String toString() {

StringBuilder sb = new StringBuilder();
sb.append("class DCRConfig {\n");

sb.append(" clientAuthenticationRequired: ").append(toIndentedString(clientAuthenticationRequired)).append("\n");
sb.append(" ssaJwks: ").append(toIndentedString(ssaJwks)).append("\n");
sb.append(" enableFapiEnforcement: ").append(toIndentedString(enableFapiEnforcement)).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");
}
}

Loading
Loading