From 1d4d0b7ae2850da6645ed0ab9d5f875403995f62 Mon Sep 17 00:00:00 2001 From: prabathabey Date: Tue, 31 May 2016 16:13:45 +0530 Subject: [PATCH] Improving certificate management webapp implementation --- .../mgt/jaxrs/api/CertificateMgtService.java | 47 +++- .../api/impl/CertificateMgtServiceImpl.java | 19 +- .../mgt/jaxrs/beans/ErrorListItem.java | 79 ++++++ .../mgt/jaxrs/beans/ErrorResponse.java | 193 +++++++++++++ .../UnexpectedServerErrorException.java | 34 +++ .../pom.xml | 4 - .../mgt/cert/jaxrs/api/Certificate.java | 123 --------- .../CertificateManagementAdminService.java | 255 ++++++++++++++++++ .../jaxrs/api/InputValidationException.java | 35 +++ .../api/UnexpectedServerErrorException.java | 34 +++ .../jaxrs/api/beans/BasePaginatedResult.java | 72 +++++ .../cert/jaxrs/api/beans/CertificateList.java | 55 ++++ .../cert/jaxrs/api/beans/ErrorListItem.java | 79 ++++++ .../cert/jaxrs/api/beans/ErrorResponse.java | 193 +++++++++++++ .../cert/jaxrs/api/impl/CertificateImpl.java | 181 ------------- ...CertificateManagementAdminServiceImpl.java | 134 +++++++++ .../jaxrs/api/util/DeviceMgtAPIUtils.java | 2 +- .../jaxrs/api/util/RequestValidationUtil.java | 48 ++++ .../src/main/webapp/META-INF/permissions.xml | 4 +- .../src/main/webapp/WEB-INF/cxf-servlet.xml | 2 +- .../src/main/webapp/WEB-INF/cxf-servlet.xml | 1 + 21 files changed, 1271 insertions(+), 323 deletions(-) create mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/beans/ErrorListItem.java create mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/beans/ErrorResponse.java create mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/exception/UnexpectedServerErrorException.java delete mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/Certificate.java create mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/CertificateManagementAdminService.java create mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/InputValidationException.java create mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/UnexpectedServerErrorException.java create mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/BasePaginatedResult.java create mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/CertificateList.java create mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ErrorListItem.java create mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ErrorResponse.java delete mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateImpl.java create mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java create mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/RequestValidationUtil.java diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/api/CertificateMgtService.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/api/CertificateMgtService.java index 6c9abc27b61..a2f298ba916 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/api/CertificateMgtService.java +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/api/CertificateMgtService.java @@ -1,9 +1,18 @@ package org.wso2.carbon.certificate.mgt.jaxrs.api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import org.wso2.carbon.apimgt.annotations.api.Permission; +import org.wso2.carbon.certificate.mgt.jaxrs.beans.ErrorResponse; +import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation; + import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +@Path("/scep") public interface CertificateMgtService { /** @@ -13,8 +22,38 @@ public interface CertificateMgtService { * @return X509Certificate type sign certificate. */ @POST - @Path("signcsr") - @Produces({MediaType.TEXT_PLAIN, MediaType.TEXT_PLAIN}) - @Consumes({MediaType.TEXT_PLAIN, MediaType.TEXT_PLAIN}) - Response getSignedCertFromCSR(String binarySecurityToken); + @Path("/sign-csr") + @Produces(MediaType.TEXT_PLAIN) + @Consumes(MediaType.TEXT_PLAIN) + @ApiOperation( + consumes = MediaType.TEXT_PLAIN, + produces = MediaType.TEXT_PLAIN, + httpMethod = "POST", + value = "Process a given CSR and return signed certificates.", + notes = "This will return a signed certificate upon a given CSR.", + tags = "Device Management") + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the device location.", + response = String.class), + @ApiResponse( + code = 304, + message = "Not Modified. \n " + + "Empty body because the client already has the latest version of the requested resource."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error occurred while retrieving signed certificate.", + response = ErrorResponse.class) + }) + @Permission(scope = "sign-csr", permissions = {"/permission/admin/device-mgt/scep/sign-csr"}) + Response getSignedCertFromCSR( + @ApiParam( + name = "If-Modified-Since", + value = "Validates if the requested variant has not been modified since the time specified", + required = false) + @HeaderParam("If-Modified-Since") String ifModifiedSince, + String binarySecurityToken); + } diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/api/impl/CertificateMgtServiceImpl.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/api/impl/CertificateMgtServiceImpl.java index e0ca24de02d..71c03b6e1ce 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/api/impl/CertificateMgtServiceImpl.java +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/api/impl/CertificateMgtServiceImpl.java @@ -5,6 +5,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException; import org.wso2.carbon.certificate.mgt.core.impl.CertificateGenerator; +import org.wso2.carbon.certificate.mgt.jaxrs.beans.ErrorResponse; +import org.wso2.carbon.certificate.mgt.jaxrs.exception.UnexpectedServerErrorException; import org.wso2.carbon.certificate.mgt.jaxrs.api.CertificateMgtService; import org.wso2.carbon.certificate.mgt.jaxrs.exception.Message; @@ -14,15 +16,16 @@ import javax.ws.rs.core.Response; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; - +@Path("/scep") public class CertificateMgtServiceImpl implements CertificateMgtService { private static Log log = LogFactory.getLog(CertificateMgtServiceImpl.class); @POST - @Path("signcsr") - @Produces({MediaType.TEXT_PLAIN, MediaType.TEXT_PLAIN}) - @Consumes({MediaType.TEXT_PLAIN, MediaType.TEXT_PLAIN}) - public Response getSignedCertFromCSR(String binarySecurityToken) { + @Path("/sign-csr") + @Produces(MediaType.TEXT_PLAIN) + @Consumes(MediaType.TEXT_PLAIN) + public Response getSignedCertFromCSR( + @HeaderParam("If-Modified-Since") String ifModifiedSince, String binarySecurityToken) { Message message = new Message(); X509Certificate signedCert; String singedCertificate; @@ -41,11 +44,13 @@ public class CertificateMgtServiceImpl implements CertificateMgtService { } catch (KeystoreException e) { String msg = "Error occurred while fetching certificate."; log.error(msg, e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + throw new UnexpectedServerErrorException(new ErrorResponse.ErrorResponseBuilder().setCode( + 500l).setMessage(msg).build()); } catch (CertificateEncodingException e) { String msg = "Error occurred while encoding the certificate."; log.error(msg, e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + throw new UnexpectedServerErrorException(new ErrorResponse.ErrorResponseBuilder().setCode( + 500l).setMessage(msg).build()); } } } diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/beans/ErrorListItem.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/beans/ErrorListItem.java new file mode 100644 index 00000000000..b9b6e6c67ce --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/beans/ErrorListItem.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.certificate.mgt.jaxrs.beans; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import javax.validation.constraints.NotNull; + +@ApiModel(description = "Error List Item") +public class ErrorListItem { + + @NotNull + private String code = null; + @NotNull + private String message = null; + + @ApiModelProperty(required = true, value = "") + @JsonProperty("code") + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public ErrorListItem() { + } + + public ErrorListItem(String code, String msg) { + this.code = code; + this.message = msg; + } + + + /** + * Description about individual errors occurred + */ + @ApiModelProperty(required = true, value = "Description about individual errors occurred") + @JsonProperty("message") + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("errorItem {\n"); + + sb.append(" code: ").append(code).append("\n"); + sb.append(" message: ").append(message).append("\n"); + sb.append("}\n"); + return sb.toString(); + } + +} diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/beans/ErrorResponse.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/beans/ErrorResponse.java new file mode 100644 index 00000000000..81b49c5da53 --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/beans/ErrorResponse.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.certificate.mgt.jaxrs.beans; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.ArrayList; +import java.util.List; + +@ApiModel(description = "Error Response") +public class ErrorResponse { + + private Long code = null; + private String message = null; + private String description = null; + private String moreInfo = null; + private List errorItems = new ArrayList<>(); + + private ErrorResponse() { + } + + @JsonProperty(value = "code") + @ApiModelProperty(required = true, value = "") + public Long getCode() { + return code; + } + + public void setCode(Long code) { + this.code = code; + } + + @JsonProperty(value = "message") + @ApiModelProperty(required = true, value = "ErrorResponse message.") + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + @JsonProperty(value = "description") + @ApiModelProperty(value = "A detail description about the error message.") + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @JsonProperty(value = "moreInfo") + @ApiModelProperty(value = "Preferably an url with more details about the error.") + public String getMoreInfo() { + return moreInfo; + } + + public void setMoreInfo(String moreInfo) { + this.moreInfo = moreInfo; + } + + public void addErrorListItem(ErrorListItem item) { + this.errorItems.add(item); + } + + /** + * If there are more than one error list them out. \nFor example, list out validation errors by each field. + */ + @JsonProperty(value = "errorItems") + @ApiModelProperty(value = "If there are more than one error list them out. \n" + + "For example, list out validation errors by each field.") + public List getErrorItems() { + return errorItems; + } + + public void setErrorItems(List error) { + this.errorItems = error; + } + + @Override + public String toString() { +// StringBuilder sb = new StringBuilder(); +// sb.append("{"); +// boolean cont = false; +// if (code != null) { +// cont = true; +// sb.append(" \"code\": ").append(code); +// } +// if (message != null) { +// if (cont) { +// sb.append(","); +// } +// cont = true; +// sb.append(" \"message\": \"").append(message).append("\""); +// } +// if (description != null) { +// if (cont) { +// sb.append(","); +// } +// cont = true; +// sb.append(" \"description\": ").append(description).append("\""); +// } +// if (moreInfo != null) { +// if (cont) { +// sb.append(","); +// } +// cont = true; +// sb.append(" \"moreInfo\": \"").append(moreInfo).append("\""); +// } +// if (error != null && error.size() > 0) { +// if (cont) { +// sb.append(","); +// } +// sb.append(" \"errorItems\": ").append(error); +// } +// sb.append("}"); +// return sb.toString(); + return null; + } + + public static class ErrorResponseBuilder { + + private Long code = null; + private String message = null; + private String description = null; + private String moreInfo = null; + private List error; + + + public ErrorResponseBuilder() { + this.error = new ArrayList<>(); + } + + public ErrorResponseBuilder setCode(long code) { + this.code = code; + return this; + } + + public ErrorResponseBuilder setMessage(String message) { + this.message = message; + return this; + } + + public ErrorResponseBuilder setDescription(String description) { + this.description = description; + return this; + } + + public ErrorResponseBuilder setMoreInfo(String moreInfo) { + this.moreInfo = moreInfo; + return this; + } + + public ErrorResponseBuilder addErrorItem(String code, String msg) { + ErrorListItem item = new ErrorListItem(); + item.setCode(code); + item.setMessage(msg); + this.error.add(item); + return this; + } + + public ErrorResponse build() { + ErrorResponse errorResponse = new ErrorResponse(); + errorResponse.setCode(code); + errorResponse.setMessage(message); + errorResponse.setErrorItems(error); + errorResponse.setDescription(description); + errorResponse.setMoreInfo(moreInfo); + return errorResponse; + } + } + +} + + diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/exception/UnexpectedServerErrorException.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/exception/UnexpectedServerErrorException.java new file mode 100644 index 00000000000..9b6e2d4ef21 --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/java/org/wso2/carbon/certificate/mgt/jaxrs/exception/UnexpectedServerErrorException.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.certificate.mgt.jaxrs.exception; + +import org.wso2.carbon.certificate.mgt.jaxrs.beans.ErrorResponse; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +public class UnexpectedServerErrorException extends WebApplicationException { + + private static final long serialVersionUID = 147943679458906890L; + + public UnexpectedServerErrorException(ErrorResponse error) { + super(Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build()); + } + +} diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml index 3b5c4a9a951..95ea9ce63a5 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml @@ -51,10 +51,6 @@ admin-certificate - - org.apache.felix - maven-scr-plugin - diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/Certificate.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/Certificate.java deleted file mode 100644 index 1192cdfa132..00000000000 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/Certificate.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.wso2.carbon.certificate.mgt.cert.jaxrs.api; - -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import org.wso2.carbon.apimgt.annotations.api.Permission; -import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.EnrollmentCertificate; -import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.common.MDMAPIException; -import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse; -import org.wso2.carbon.device.mgt.common.PaginationResult; - -import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -public interface Certificate { - - /** - * Save a list of certificates and relevant information in the database. - * - * @param enrollmentCertificates List of all the certificates which includes the tenant id, certificate as - * a pem and a serial number. - * @return Status of the data persist operation. - */ - @POST - @ApiOperation( - consumes = MediaType.APPLICATION_JSON + ", " + MediaType.APPLICATION_XML, - produces = MediaType.APPLICATION_JSON + ", " + MediaType.APPLICATION_XML, - httpMethod = "POST", - value = "Adding an SSL Certificate", - notes = "Add a new SSL certificate to the client end database") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "Added successfully"), - @ApiResponse(code = 500, message = "Error occurred while saving the certificate") - }) - @Permission(scope = "certificate-modify", permissions = {"/permission/admin/device-mgt/certificate/save"}) - Response saveCertificate(@HeaderParam("Accept") String acceptHeader, - @ApiParam(name = "enrollmentCertificates", value = "certificate with serial, " - + "pem and tenant id", required = true) EnrollmentCertificate[] - enrollmentCertificates); - - /** - * Get a certificate when the serial number is given. - * - * @param serialNumber serial of the certificate needed. - * @return certificate response. - */ - @GET - @Path("{serialNumber}") - @ApiOperation( - consumes = MediaType.APPLICATION_JSON + ", " + MediaType.APPLICATION_XML, - produces = MediaType.APPLICATION_JSON + ", " + MediaType.APPLICATION_XML, - httpMethod = "GET", - value = "Getting Details of an SSL Certificate", - notes = "Get the client side SSL certificate details", - response = CertificateResponse.class) - @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = CertificateResponse.class), - @ApiResponse(code = 400, message = "Notification status updated successfully"), - @ApiResponse(code = 500, message = "Error occurred while converting PEM file to X509Certificate") - }) - @Permission(scope = "certificate-view", permissions = {"/permission/admin/device-mgt/certificate/view"}) - Response getCertificate(@HeaderParam("Accept") String acceptHeader, - @ApiParam(name = "serialNumber", value = "Provide the serial number of the " - + "certificate that you wish to get the details of", required = true) - @PathParam("serialNumber") String serialNumber); - - /** - * Get all certificates in a paginated manner. - * - * @param startIndex index of the first record to be fetched - * @param length number of records to be fetched starting from the start index. - * @return paginated result of certificate. - * @throws MDMAPIException - */ - @GET - @Path("paginate") - @ApiOperation( - consumes = MediaType.APPLICATION_JSON + ", " + MediaType.APPLICATION_XML, - produces = MediaType.APPLICATION_JSON + ", " + MediaType.APPLICATION_XML, - httpMethod = "GET", - value = "Getting the Certificate Details in a Paginated Manner", - notes = "You will have many certificates used for mutual SSL. In a situation where you wish to " - + "view all the certificate details, it is not feasible to show all the details on one " - + "page therefore the details are paginated", - response = PaginationResult.class) - @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = PaginationResult.class), - @ApiResponse(code = 400, message = "Invalid start index"), - @ApiResponse(code = 400, message = "Invalid length value"), - @ApiResponse(code = 500, message = "Error occurred while fetching all certificates") - }) - @Permission(scope = "certificate-view", permissions = {"/permission/admin/device-mgt/certificate/view"}) - Response getAllCertificates(@HeaderParam("Accept") String acceptHeader, - @ApiParam(name = "start", - value = "Provide the starting pagination index as the value", required = true) - @QueryParam("start") int startIndex, - @ApiParam(name = "length", value = "Provide how many certificate details you" - + " require from the starting pagination index as the value", - required = true) @QueryParam("length") int length) throws MDMAPIException; - - @DELETE - @Path("{serialNumber}") - @ApiOperation( - consumes = MediaType.APPLICATION_JSON + ", " + MediaType.APPLICATION_XML, - produces = MediaType.APPLICATION_JSON + ", " + MediaType.APPLICATION_XML, - httpMethod = "DELETE", - value = "Deleting an SSL Certificate", - notes = "Delete an SSL certificate that's on the client end", - response = boolean.class) - @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK"), - @ApiResponse(code = 400, message = "Invalid start index"), - @ApiResponse(code = 500, message = "Error when deleting the certificate" - ) }) - @Permission(scope = "certificate-modify", permissions = {"/permission/admin/device-mgt/certificate/remove"}) - Response removeCertificate(@HeaderParam("Accept") String acceptHeader, - @ApiParam(name = "serialNumber", value = "Provide the serial number of the " - + "certificate that you wish to delete", required = true) - @PathParam("serialNumber") String serialNumber) throws MDMAPIException; - -} diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/CertificateManagementAdminService.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/CertificateManagementAdminService.java new file mode 100644 index 00000000000..3f9cf9c4755 --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/CertificateManagementAdminService.java @@ -0,0 +1,255 @@ +package org.wso2.carbon.certificate.mgt.cert.jaxrs.api; + +import io.swagger.annotations.*; +import org.wso2.carbon.apimgt.annotations.api.Permission; +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.CertificateList; +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.EnrollmentCertificate; +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ErrorResponse; +import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse; + +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@Api(value = "Certificate Management", description = "This API carries all certificate management related operations " + + "such as get all the available devices, etc.") +@Path("/certificates") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public interface CertificateManagementAdminService { + + /** + * Save a list of certificates and relevant information in the database. + * + * @param enrollmentCertificates List of all the certificates which includes the tenant id, certificate as + * a pem and a serial number. + * @return Status of the data persist operation. + */ + @POST + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Add a SSL certificate", + notes = "Add a new SSL certificate", + tags = "Certificate Management") + @ApiResponses( + value = { + @ApiResponse( + code = 201, + message = "Created. \n Certificates have successfully been added", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The URL of the added certificates."), + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests.")}), + @ApiResponse( + code = 303, + message = "See Other. \n Source can be retrieved from the URL specified at the Location header.", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The Source URL of the document.")}), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error."), + @ApiResponse( + code = 415, + message = "Unsupported media type. \n The entity of the request was in a not supported format."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while adding certificates.", + response = ErrorResponse.class) + }) + @Permission(scope = "certificate-modify", permissions = {"/permission/admin/device-mgt/certificate/save"}) + Response addCertificate( + @ApiParam( + name = "enrollmentCertificates", + value = "certificate with serial, " + + "pem and tenant id", + required = true) EnrollmentCertificate[] enrollmentCertificates); + + /** + * Get a certificate when the serial number is given. + * + * @param serialNumber serial of the certificate needed. + * @return certificate response. + */ + @GET + @Path("/{serialNumber}") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting Details of an SSL CertificateManagementAdminService", + notes = "Get the client side SSL certificate details", + tags = "Certificate Management") + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched information of the device.", + response = CertificateResponse.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 304, + message = "Not Modified. \n " + + "Empty body because the client already has the latest version of the requested resource."), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n No device is found under the provided type and id."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n " + + "Server error occurred while retrieving information requested certificate.", + response = ErrorResponse.class) + }) + @Permission(scope = "certificate-view", permissions = {"/permission/admin/device-mgt/certificate/view"}) + Response getCertificate( + @ApiParam(name = "serialNumber", + value = "Provide the serial number of the certificate that you wish to get the details of", + required = true) + @PathParam("serialNumber") String serialNumber, + @ApiParam( + name = "If-Modified-Since", + value = "Validates if the requested variant has not been modified since the time specified", + required = false) + @HeaderParam("If-Modified-Since") String ifModifiedSince + ); + + /** + * Get all certificates in a paginated manner. + * + * @return paginated result of certificate. + */ + @GET + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Get certificates", + notes = "You will have many certificates used for mutual SSL. In a situation where you wish to " + + "view all the certificate details, it is not feasible to show all the details on one " + + "page therefore the details are paginated", + tags = "Certificate Management" + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK. \n List of certificates enrolled in the system", + response = CertificateList.class, + responseContainer = "List", + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests.")}), + @ApiResponse( + code = 303, + message = "See Other. \n " + + "Source can be retrieved from the URL specified at the Location header.", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The Source URL of the document.")}), + @ApiResponse( + code = 304, + message = "Not Modified. \n " + + "Empty body because the client already has the latest version of the requested resource."), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 406, + message = "Not Acceptable. \n The requested media type is not supported."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n " + + "Server error occurred while retrieving all certificates enrolled in the system.", + response = ErrorResponse.class) + }) + @Permission(scope = "certificate-view", permissions = {"/permission/admin/device-mgt/certificate/view"}) + Response getAllCertificates( + @ApiParam( + name = "offset", + value = "Starting point within the complete list of items qualified.", + required = false) + @QueryParam("offset") int offset, + @ApiParam( + name = "limit", + value = "Maximum size of resource array to return.", + required = false) + @QueryParam("limit") int limit, + @ApiParam( + name = "If-Modified-Since", + value = "Validates if the requested variant has not been modified since the time specified", + required = false) + @HeaderParam("If-Modified-Since") String ifModifiedSince); + + @DELETE + @Path("/{serialNumber}") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "DELETE", + value = "Delete an SSL certificate", + notes = "Delete an SSL certificate that's on the client end") + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK. \n Certificate has successfully been removed"), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n Resource to be deleted does not exist."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n " + + "Server error occurred while removing the certificate.", + response = ErrorResponse.class)}) + @Permission(scope = "certificate-modify", permissions = {"/permission/admin/device-mgt/certificate/remove"}) + Response removeCertificate( + @ApiParam( + name = "serialNumber", + value = "Provide the serial number of the " + + "certificate that you wish to delete", + required = true) + @PathParam("serialNumber") String serialNumber); + +} diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/InputValidationException.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/InputValidationException.java new file mode 100644 index 00000000000..08048069677 --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/InputValidationException.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.certificate.mgt.cert.jaxrs.api; + +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ErrorResponse; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; +import java.io.Serializable; + +public class InputValidationException extends WebApplicationException implements Serializable { + + private static final long serialVersionUID = 147843589458906890L; + + public InputValidationException(ErrorResponse error) { + super(Response.status(Response.Status.BAD_REQUEST).entity(error).build()); + } + +} diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/UnexpectedServerErrorException.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/UnexpectedServerErrorException.java new file mode 100644 index 00000000000..28eaed09bc2 --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/UnexpectedServerErrorException.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.certificate.mgt.cert.jaxrs.api; + +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ErrorResponse; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +public class UnexpectedServerErrorException extends WebApplicationException { + + private static final long serialVersionUID = 147943679458906890L; + + public UnexpectedServerErrorException(ErrorResponse error) { + super(Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build()); + } + +} diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/BasePaginatedResult.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/BasePaginatedResult.java new file mode 100644 index 00000000000..b1fe40a9ec7 --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/BasePaginatedResult.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.certificate.mgt.cert.jaxrs.api.beans; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModelProperty; + +public class BasePaginatedResult { + + private int count; + private String next; + private String previous; + + /** + * Number of Devices returned. + */ + @ApiModelProperty(value = "Number of resources returned.") + @JsonProperty("count") + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + + /** + * Link to the next subset of resources qualified. \nEmpty if no more resources are to be returned. + */ + @ApiModelProperty(value = "Link to the next subset of resources qualified. \n " + + "Empty if no more resources are to be returned.") + @JsonProperty("next") + public String getNext() { + return next; + } + + public void setNext(String next) { + this.next = next; + } + + /** + * Link to the previous subset of resources qualified. \nEmpty if current subset is the first subset returned. + */ + @ApiModelProperty(value = "Link to the previous subset of resources qualified. \n" + + "Empty if current subset is the first subset returned.") + @JsonProperty("previous") + public String getPrevious() { + return previous; + } + + public void setPrevious(String previous) { + this.previous = previous; + } + +} diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/CertificateList.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/CertificateList.java new file mode 100644 index 00000000000..2c61a4b23a0 --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/CertificateList.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.certificate.mgt.cert.jaxrs.api.beans; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModelProperty; +import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse; + +import java.util.ArrayList; +import java.util.List; + +public class CertificateList extends BasePaginatedResult { + + private List certificates = new ArrayList<>(); + + @ApiModelProperty(value = "List of certificates returned") + @JsonProperty("certificates") + public List getList() { + return certificates; + } + + public void setList(List certificates) { + this.certificates = certificates; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{\n"); + + sb.append(" count: ").append(getCount()).append(",\n"); + sb.append(" next: ").append(getNext()).append(",\n"); + sb.append(" previous: ").append(getPrevious()).append(",\n"); + sb.append(" certificates: [").append(certificates).append("\n"); + sb.append("]}\n"); + return sb.toString(); + } + +} diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ErrorListItem.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ErrorListItem.java new file mode 100644 index 00000000000..dc3a94efb11 --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ErrorListItem.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.certificate.mgt.cert.jaxrs.api.beans; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import javax.validation.constraints.NotNull; + +@ApiModel(description = "Error List Item") +public class ErrorListItem { + + @NotNull + private String code = null; + @NotNull + private String message = null; + + @ApiModelProperty(required = true, value = "") + @JsonProperty("code") + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public ErrorListItem() { + } + + public ErrorListItem(String code, String msg) { + this.code = code; + this.message = msg; + } + + + /** + * Description about individual errors occurred + */ + @ApiModelProperty(required = true, value = "Description about individual errors occurred") + @JsonProperty("message") + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("errorItem {\n"); + + sb.append(" code: ").append(code).append("\n"); + sb.append(" message: ").append(message).append("\n"); + sb.append("}\n"); + return sb.toString(); + } + +} diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ErrorResponse.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ErrorResponse.java new file mode 100644 index 00000000000..f8101d796f3 --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ErrorResponse.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.certificate.mgt.cert.jaxrs.api.beans; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.ArrayList; +import java.util.List; + +@ApiModel(description = "Error Response") +public class ErrorResponse { + + private Long code = null; + private String message = null; + private String description = null; + private String moreInfo = null; + private List errorItems = new ArrayList<>(); + + private ErrorResponse() { + } + + @JsonProperty(value = "code") + @ApiModelProperty(required = true, value = "") + public Long getCode() { + return code; + } + + public void setCode(Long code) { + this.code = code; + } + + @JsonProperty(value = "message") + @ApiModelProperty(required = true, value = "ErrorResponse message.") + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + @JsonProperty(value = "description") + @ApiModelProperty(value = "A detail description about the error message.") + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @JsonProperty(value = "moreInfo") + @ApiModelProperty(value = "Preferably an url with more details about the error.") + public String getMoreInfo() { + return moreInfo; + } + + public void setMoreInfo(String moreInfo) { + this.moreInfo = moreInfo; + } + + public void addErrorListItem(ErrorListItem item) { + this.errorItems.add(item); + } + + /** + * If there are more than one error list them out. \nFor example, list out validation errors by each field. + */ + @JsonProperty(value = "errorItems") + @ApiModelProperty(value = "If there are more than one error list them out. \n" + + "For example, list out validation errors by each field.") + public List getErrorItems() { + return errorItems; + } + + public void setErrorItems(List error) { + this.errorItems = error; + } + + @Override + public String toString() { +// StringBuilder sb = new StringBuilder(); +// sb.append("{"); +// boolean cont = false; +// if (code != null) { +// cont = true; +// sb.append(" \"code\": ").append(code); +// } +// if (message != null) { +// if (cont) { +// sb.append(","); +// } +// cont = true; +// sb.append(" \"message\": \"").append(message).append("\""); +// } +// if (description != null) { +// if (cont) { +// sb.append(","); +// } +// cont = true; +// sb.append(" \"description\": ").append(description).append("\""); +// } +// if (moreInfo != null) { +// if (cont) { +// sb.append(","); +// } +// cont = true; +// sb.append(" \"moreInfo\": \"").append(moreInfo).append("\""); +// } +// if (error != null && error.size() > 0) { +// if (cont) { +// sb.append(","); +// } +// sb.append(" \"errorItems\": ").append(error); +// } +// sb.append("}"); +// return sb.toString(); + return null; + } + + public static class ErrorResponseBuilder { + + private Long code = null; + private String message = null; + private String description = null; + private String moreInfo = null; + private List error; + + + public ErrorResponseBuilder() { + this.error = new ArrayList<>(); + } + + public ErrorResponseBuilder setCode(long code) { + this.code = code; + return this; + } + + public ErrorResponseBuilder setMessage(String message) { + this.message = message; + return this; + } + + public ErrorResponseBuilder setDescription(String description) { + this.description = description; + return this; + } + + public ErrorResponseBuilder setMoreInfo(String moreInfo) { + this.moreInfo = moreInfo; + return this; + } + + public ErrorResponseBuilder addErrorItem(String code, String msg) { + ErrorListItem item = new ErrorListItem(); + item.setCode(code); + item.setMessage(msg); + this.error.add(item); + return this; + } + + public ErrorResponse build() { + ErrorResponse errorResponse = new ErrorResponse(); + errorResponse.setCode(code); + errorResponse.setMessage(message); + errorResponse.setErrorItems(error); + errorResponse.setDescription(description); + errorResponse.setMoreInfo(moreInfo); + return errorResponse; + } + } + +} + + diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateImpl.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateImpl.java deleted file mode 100644 index d97d5ab4b1f..00000000000 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateImpl.java +++ /dev/null @@ -1,181 +0,0 @@ -package org.wso2.carbon.certificate.mgt.cert.jaxrs.api.impl; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.Certificate; -import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.EnrollmentCertificate; -import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.common.MDMAPIException; -import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.exception.Message; -import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.util.DeviceMgtAPIUtils; -import org.wso2.carbon.certificate.mgt.core.dao.CertificateManagementDAOException; -import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse; -import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException; -import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; -import org.wso2.carbon.context.PrivilegedCarbonContext; -import org.wso2.carbon.device.mgt.common.PaginationRequest; -import org.wso2.carbon.device.mgt.common.PaginationResult; - -import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.util.ArrayList; -import java.util.List; - -public class CertificateImpl implements Certificate { - - private static Log log = LogFactory.getLog(CertificateImpl.class); - - /** - * Save a list of certificates and relevant information in the database. - * - * @param enrollmentCertificates List of all the certificates which includes the tenant id, certificate as - * a pem and a serial number. - * @return Status of the data persist operation. - */ - @POST - public Response saveCertificate(@HeaderParam("Accept") String acceptHeader, - EnrollmentCertificate[] enrollmentCertificates) { - MediaType responseMediaType = DeviceMgtAPIUtils.getResponseMediaType(acceptHeader); - CertificateManagementService certificateService; - List certificates = new ArrayList<>(); - org.wso2.carbon.certificate.mgt.core.bean.Certificate certificate; - certificateService = DeviceMgtAPIUtils.getCertificateManagementService(); - try { - for (EnrollmentCertificate enrollmentCertificate : enrollmentCertificates) { - certificate = new org.wso2.carbon.certificate.mgt.core.bean.Certificate(); - certificate.setTenantId(PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId()); - certificate.setSerial(enrollmentCertificate.getSerial()); - certificate.setCertificate(certificateService.pemToX509Certificate(enrollmentCertificate.getPem())); - certificates.add(certificate); - } - certificateService.saveCertificate(certificates); - return Response.status(Response.Status.CREATED).entity("Added successfully."). - type(responseMediaType).build(); - } catch (KeystoreException e) { - String msg = "Error occurred while converting PEM file to X509Certificate."; - log.error(msg, e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).type(responseMediaType).build(); - } - } - - /** - * Get a certificate when the serial number is given. - * - * @param serialNumber serial of the certificate needed. - * @return certificate response. - */ - @GET - @Path("{serialNumber}") - public Response getCertificate(@HeaderParam("Accept") String acceptHeader, - @PathParam("serialNumber") String serialNumber) { - MediaType responseMediaType = DeviceMgtAPIUtils.getResponseMediaType(acceptHeader); - Message message = new Message(); - - if (serialNumber == null || serialNumber.isEmpty()) { - message.setErrorMessage("Invalid serial number"); - message.setDiscription("Serial number is missing or invalid."); - return Response.status(Response.Status.BAD_REQUEST).entity(message).type(responseMediaType).build(); - } - - CertificateManagementService certificateService = DeviceMgtAPIUtils.getCertificateManagementService(); - List certificateResponse; - try { - certificateResponse = certificateService.searchCertificates(serialNumber); - return Response.status(Response.Status.OK).entity(certificateResponse).type(responseMediaType).build(); - } catch (CertificateManagementDAOException e) { - String msg = "Error occurred while converting PEM file to X509Certificate"; - log.error(msg, e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).type(responseMediaType).build(); - } - } - - /** - * Get all certificates in a paginated manner. - * - * @param startIndex index of the first record to be fetched - * @param length number of records to be fetched starting from the start index. - * @return paginated result of certificate. - * @throws MDMAPIException - */ - @GET - @Path("paginate") - public Response getAllCertificates(@HeaderParam("Accept") String acceptHeader, - @QueryParam("start") int startIndex, - @QueryParam("length") int length) - throws MDMAPIException { - MediaType responseMediaType = DeviceMgtAPIUtils.getResponseMediaType(acceptHeader); - Message message = new Message(); - - if (startIndex < 0) { - message.setErrorMessage("Invalid start index."); - message.setDiscription("Start index cannot be less that 0."); - return Response.status(Response.Status.BAD_REQUEST).entity(message).type(responseMediaType).build(); - } else if (length <= 0) { - message.setErrorMessage("Invalid length value."); - message.setDiscription("Length should be a positive integer."); - return Response.status(Response.Status.BAD_REQUEST).entity(message).type(responseMediaType).build(); - } - - CertificateManagementService certificateService = DeviceMgtAPIUtils.getCertificateManagementService(); - PaginationRequest paginationRequest = new PaginationRequest(startIndex, length); - try { - PaginationResult certificates = certificateService.getAllCertificates(paginationRequest); - return Response.status(Response.Status.OK).entity(certificates).type(responseMediaType).build(); - } catch (CertificateManagementDAOException e) { - String msg = "Error occurred while fetching all certificates."; - log.error(msg, e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).type(responseMediaType).build(); - } - } - - /** - * Get all certificates - * - * @return certificate details in an array. - * @throws MDMAPIException - */ - @GET - public Response getAllCertificates(@HeaderParam("Accept") String acceptHeader) - throws MDMAPIException { - MediaType responseMediaType = DeviceMgtAPIUtils.getResponseMediaType(acceptHeader); - - CertificateManagementService certificateService = DeviceMgtAPIUtils.getCertificateManagementService(); - try { - List certificates = certificateService.getCertificates(); - return Response.status(Response.Status.OK).entity(certificates).type(responseMediaType).build(); - } catch (CertificateManagementDAOException e) { - String msg = "Error occurred while fetching all certificates."; - log.error(msg, e); - throw new MDMAPIException(msg, e); - } - } - - @DELETE - @Path("{serialNumber}") - public Response removeCertificate(@HeaderParam("Accept") String acceptHeader, - @PathParam("serialNumber") String serialNumber) throws MDMAPIException { - MediaType responseMediaType = DeviceMgtAPIUtils.getResponseMediaType(acceptHeader); - Message message = new Message(); - - if (serialNumber == null || serialNumber.isEmpty()) { - message.setErrorMessage("Invalid serial number"); - message.setDiscription("Serial number is missing or invalid."); - return Response.status(Response.Status.BAD_REQUEST).entity(message).type(responseMediaType).build(); - } - - CertificateManagementService certificateService = DeviceMgtAPIUtils.getCertificateManagementService(); - boolean deleted; - try { - deleted = certificateService.removeCertificate(serialNumber); - if(deleted){ - return Response.status(Response.Status.OK).entity(deleted).type(responseMediaType).build(); - } else { - return Response.status(Response.Status.GONE).entity(deleted).type(responseMediaType).build(); - } - } catch (CertificateManagementDAOException e) { - String msg = "Error occurred while converting PEM file to X509Certificate"; - log.error(msg, e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).type(responseMediaType).build(); - } - } -} diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java new file mode 100644 index 00000000000..ad3b1e81080 --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java @@ -0,0 +1,134 @@ +package org.wso2.carbon.certificate.mgt.cert.jaxrs.api.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.CertificateManagementAdminService; +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.UnexpectedServerErrorException; +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.CertificateList; +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.EnrollmentCertificate; +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ErrorResponse; +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.util.DeviceMgtAPIUtils; +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.util.RequestValidationUtil; +import org.wso2.carbon.certificate.mgt.core.dao.CertificateManagementDAOException; +import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse; +import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException; +import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.PaginationResult; + +import javax.ws.rs.*; +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.List; + +@Path("/certificates") +public class CertificateManagementAdminServiceImpl implements CertificateManagementAdminService { + + private static Log log = LogFactory.getLog(CertificateManagementAdminServiceImpl.class); + + /** + * Save a list of certificates and relevant information in the database. + * + * @param enrollmentCertificates List of all the certificates which includes the tenant id, certificate as + * a pem and a serial number. + * @return Status of the data persist operation. + */ + @POST + public Response addCertificate(EnrollmentCertificate[] enrollmentCertificates) { + CertificateManagementService certificateService; + List certificates = new ArrayList<>(); + org.wso2.carbon.certificate.mgt.core.bean.Certificate certificate; + certificateService = DeviceMgtAPIUtils.getCertificateManagementService(); + try { + for (EnrollmentCertificate enrollmentCertificate : enrollmentCertificates) { + certificate = new org.wso2.carbon.certificate.mgt.core.bean.Certificate(); + certificate.setTenantId(PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId()); + certificate.setSerial(enrollmentCertificate.getSerial()); + certificate.setCertificate(certificateService.pemToX509Certificate(enrollmentCertificate.getPem())); + certificates.add(certificate); + } + certificateService.saveCertificate(certificates); + return Response.status(Response.Status.CREATED).entity("Added successfully.").build(); + } catch (KeystoreException e) { + String msg = "Error occurred while converting PEM file to X509Certificate."; + log.error(msg, e); + throw new UnexpectedServerErrorException( + new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()); + } + } + + /** + * Get a certificate when the serial number is given. + * + * @param serialNumber serial of the certificate needed. + * @return certificate response. + */ + @GET + @Path("/{serialNumber}") + public Response getCertificate( + @PathParam("serialNumber") String serialNumber, + @HeaderParam("If-Modified-Since") String ifModifiedSince) { + RequestValidationUtil.validateSerialNumber(serialNumber); + + CertificateManagementService certificateService = DeviceMgtAPIUtils.getCertificateManagementService(); + List certificateResponse; + try { + certificateResponse = certificateService.searchCertificates(serialNumber); + return Response.status(Response.Status.OK).entity(certificateResponse).build(); + } catch (CertificateManagementDAOException e) { + String msg = "Error occurred while converting PEM file to X509Certificate"; + log.error(msg, e); + throw new UnexpectedServerErrorException( + new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()); + } + } + + /** + * Get all certificates in a paginated manner. + * + * @param offset index of the first record to be fetched + * @param limit number of records to be fetched starting from the start index. + * @return paginated result of certificate. + */ + @GET + public Response getAllCertificates( + @QueryParam("offset") int offset, + @QueryParam("limit") int limit, + @HeaderParam("If-Modified-Since") String ifModifiedSince) { + RequestValidationUtil.validatePaginationInfo(offset, limit); + + CertificateManagementService certificateService = DeviceMgtAPIUtils.getCertificateManagementService(); + PaginationRequest paginationRequest = new PaginationRequest(offset, limit); + try { + PaginationResult result = certificateService.getAllCertificates(paginationRequest); + CertificateList certificates = new CertificateList(); + certificates.setCount(result.getRecordsTotal()); + certificates.setList((List) result.getData()); + return Response.status(Response.Status.OK).entity(certificates).build(); + } catch (CertificateManagementDAOException e) { + String msg = "Error occurred while fetching all certificates."; + log.error(msg, e); + throw new UnexpectedServerErrorException( + new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()); + } + } + + @DELETE + @Path("/{serialNumber}") + public Response removeCertificate(@PathParam("serialNumber") String serialNumber) { + RequestValidationUtil.validateSerialNumber(serialNumber); + + CertificateManagementService certificateService = DeviceMgtAPIUtils.getCertificateManagementService(); + try { + certificateService.removeCertificate(serialNumber); + return Response.status(Response.Status.OK).entity("Certificate that carries the serial number '" + + serialNumber + " has been removed").build(); + } catch (CertificateManagementDAOException e) { + String msg = "Error occurred while converting PEM file to X509Certificate"; + log.error(msg, e); + throw new UnexpectedServerErrorException( + new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()); + } + } +} diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/DeviceMgtAPIUtils.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/DeviceMgtAPIUtils.java index 40026011f13..4419bcf79ae 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/DeviceMgtAPIUtils.java +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/DeviceMgtAPIUtils.java @@ -41,7 +41,7 @@ public class DeviceMgtAPIUtils { ctx.getOSGiService(CertificateManagementService.class, null); if (certificateManagementService == null) { - String msg = "CertificateImpl Management service not initialized."; + String msg = "CertificateManagementAdminServiceImpl Management service not initialized."; log.error(msg); throw new IllegalStateException(msg); } diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/RequestValidationUtil.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/RequestValidationUtil.java new file mode 100644 index 00000000000..233112c342e --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/RequestValidationUtil.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.certificate.mgt.cert.jaxrs.api.util; + +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ErrorResponse; +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.InputValidationException; + +public class RequestValidationUtil { + + public static void validateSerialNumber(String serialNumber) { + if (serialNumber == null || serialNumber.isEmpty()) { + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage( + "Serial number cannot be null or empty").build()); + } + } + + public static void validatePaginationInfo(int offset, int limit) { + if (offset < 0) { + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage( + "Offset number cannot be negative").build()); + } + if (limit < 0) { + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage( + "Limit number cannot be negative").build()); + } + } + + +} diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/webapp/META-INF/permissions.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/webapp/META-INF/permissions.xml index 955b726ad43..774a21e13af 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/webapp/META-INF/permissions.xml +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/webapp/META-INF/permissions.xml @@ -38,7 +38,7 @@ emm_admin - + Save certificate in the database /device-mgt/admin/certificate/save @@ -63,5 +63,5 @@ /certificates/* DELETE - + diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/webapp/WEB-INF/cxf-servlet.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/webapp/WEB-INF/cxf-servlet.xml index fc3c9ef2401..a955e2a17d0 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/webapp/WEB-INF/cxf-servlet.xml +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -59,7 +59,7 @@ - + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml index 7bb3dd412ec..42eb1188dda 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -55,6 +55,7 @@ +