Skip to content

Input Validation and Format Restrictions

1. Purpose and Scope

Support STIG compliance with SI-10-05.

2. Definition of Invalid Input

Type
Incorrect data types
Missing required fields
Malformed input
Illegal characters
Excessively long input
Business rule violations

To enforce input restrictions and ensure data integrity, MCT implements several custom validators to validate incoming requests

public enum ValidationType {
    NULL(null),
    STRING(new StringValidator()),
    STRING_NO_NULL(new StringValidator(false)),
    STRING_200(new StringValidator(200)),
    STRING_120(new StringValidator(120)),
    STRING_20(new StringValidator(20)),
    STRING_50(new StringValidator(50)),
    STRING_80(new StringValidator(80)),
    STRING_MIN_2(new StringValidator(Integer.MAX_VALUE, 2)),
    STRING_YYYYMMDD(new StringDateValidator(StringDateValidator.YYYYMMDD)),
    STRING_YYYYMMDDNU(new StringDateValidator(StringDateValidator.YYYYMMDD, true)),
    LONG(new LongValidator()),
    LONG_5(new LongValidator(5)),
    LONG_LIST(new LongListValidator()),
    IP(new RegexValidator("^(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])$", "illegal ip address")),
    TIME(new TimeValidator("yyyy-MM-dd HH:mm:ss")),
    TIME_UNIT(new RegexValidator("^(?i)(day|hour)$", "unit only accepts 'day' or 'hour'")),
    ...
}

2.1 Examples

  • Incorrect data types

    /mpi/report/failure/{startDate}

img_1.png

/mpi/clusterlist/queryCluster4HoursStatus

img_1.png

  • Missing required fields

img_1.png

img_1.png

  • Malformed input

img_1.png

img_1.png

  • Excessively long input

    /mpi/serverdetail/showGSBDetail

img_1.png

/cluster/{clusterName}/server/{serverIP}

img_1.png

  • Business rule violations

img_1.png

img_1.png

3. Global Exception Handling

To prevent stack traces from being exposed to clients, a global exception handling mechanism have been implemented.

@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(PlatformException.class)
    public ResponseEntity<DtoBase> handlePlatformException(PlatformException e) {
        logger.error("Got a platform exception", e);
        return ResponseEntity
                .status(HttpStatus.INTERNAL_SERVER_ERROR)
                .contentType(MediaType.APPLICATION_JSON)
                .body(new ResultDto<>(e));
    }

    @ExceptionHandler(PlatformRuntimeException.class)
    public ResponseEntity<DtoBase> handlePlatformRuntimeException(PlatformRuntimeException e) {
        logger.error("Got a platform runtime exception", e);
        return ResponseEntity
                .status(e.getErrorStatus().getHttpStatus())
                .contentType(MediaType.APPLICATION_JSON)
                .body(new ResultDto<>(e));
    }

    @ExceptionHandler(HttpMessageConversionException.class)
    public ResponseEntity<DtoBase> handleHttpMessageConversionException(HttpMessageConversionException e) {
        logger.error("Got a http exception", e);
        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .contentType(MediaType.APPLICATION_JSON)
                .body(new EmptyDto(ErrorCode.INVALID_INPUT_PARA,
                "Error while processing http request, please check your request path / payload. detail: " + e.getMessage()));
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<EmptyDto> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getFieldErrors().forEach(error ->
                errors.put(error.getField(), error.getDefaultMessage()));
        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .contentType(MediaType.APPLICATION_JSON)
                .body(new EmptyDto(ErrorCode.INVALID_INPUT_PARA,
                        "Error validating payload, detail: " + String.join(", ", errors.values())));
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<DtoBase> handleCommonException(Exception e) {
        logger.error("Got a general exception", e);
        return ResponseEntity
                .status(HttpStatus.INTERNAL_SERVER_ERROR)
                .contentType(MediaType.APPLICATION_JSON)
                .body(new EmptyDto(ErrorCode.NONONO, "Platform internal error: " + e.getMessage()));
    }
}