Skip to content

Commit

Permalink
Merge pull request #23 from WorldHealthOrganization/feat/trusted-issuer
Browse files Browse the repository at this point in the history
Add TrustedIssuer
  • Loading branch information
f11h committed Feb 16, 2022
2 parents c5d39bf + 9f30be8 commit 85ff8f2
Show file tree
Hide file tree
Showing 7 changed files with 479 additions and 1 deletion.
107 changes: 107 additions & 0 deletions src/main/java/eu/europa/ec/dgc/gateway/entity/TrustedIssuerEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*-
* ---license-start
* WHO Digital Documentation Covid Certificate Gateway Service / ddcc-gateway
* ---
* Copyright (C) 2022 T-Systems International GmbH and all other contributors
* ---
* Licensed 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.
* ---license-end
*/

package eu.europa.ec.dgc.gateway.entity;

import java.time.ZonedDateTime;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Getter;
import lombok.Setter;


@Getter
@Setter
@Entity
@Table(name = "trusted_issuer")
public class TrustedIssuerEntity extends FederatedEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;

/**
* Timestamp of the Record.
*/
@Column(name = "created_at", nullable = false)
private ZonedDateTime createdAt = ZonedDateTime.now();

/**
* ISO 3166 Alpha-2 Country Code
* (plus code "EU" for administrative European Union entries).
*/
@Column(name = "country", nullable = false, length = 2)
private String country;

/**
* URL of the service, can be HTTP(s) or DID URL.
*/
@Column(name = "url", nullable = false, length = 1024)
private String url;

/**
* Name of the service.
*/
@Column(name = "name", nullable = false, length = 512)
private String name;

/**
* Type of the certificate (Authentication, Upload, CSCA).
*/
@Column(name = "url_type", nullable = false, length = 25)
@Enumerated(EnumType.STRING)
private UrlType urlType;

/**
* SHA-256 Thumbprint of the certificate (hex encoded).
*/
@Column(name = "thumbprint", length = 64)
private String thumbprint;

/**
* SSL Certificate of the endpoint (if applicable).
*/
@Column(name = "ssl_public_key", length = 2048)
private String sslPublicKey;

/**
* Type of Key Storage. E.g JWKS, DIDDocument etc. (If applicable)
*/
@Column(name = "key_storage_type", length = 128)
private String keyStorageType;

/**
* Signature of the TrustAnchor.
*/
@Column(name = "signature", nullable = false, length = 6000)
String signature;

public enum UrlType {
HTTP,
DID
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*-
* ---license-start
* WHO Digital Documentation Covid Certificate Gateway Service / ddcc-gateway
* ---
* Copyright (C) 2022 T-Systems International GmbH and all other contributors
* ---
* Licensed 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.
* ---license-end
*/

package eu.europa.ec.dgc.gateway.repository;

import eu.europa.ec.dgc.gateway.entity.TrustedIssuerEntity;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;


public interface TrustedIssuerRepository extends JpaRepository<TrustedIssuerEntity, Long> {

List<TrustedIssuerEntity> getAllByCountry(String country);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package eu.europa.ec.dgc.gateway.restapi.controller;

import eu.europa.ec.dgc.gateway.config.OpenApiConfig;
import eu.europa.ec.dgc.gateway.restapi.dto.ProblemReportDto;
import eu.europa.ec.dgc.gateway.restapi.dto.TrustedIssuerDto;
import eu.europa.ec.dgc.gateway.restapi.filter.CertificateAuthenticationFilter;
import eu.europa.ec.dgc.gateway.restapi.filter.CertificateAuthenticationRequired;
import eu.europa.ec.dgc.gateway.restapi.mapper.GwTrustedIssuerMapper;
import eu.europa.ec.dgc.gateway.service.TrustedIssuerService;
import eu.europa.ec.dgc.gateway.utils.DgcMdc;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/trust/issuers")
@RequiredArgsConstructor
@Validated
@Slf4j
public class TrustedIssuerController {


private final TrustedIssuerService trustedIssuerService;

private final GwTrustedIssuerMapper trustedIssuerMapper;

private static final String MDC_PROP_DOWNLOAD_ISSUERS_COUNT = "downloadedIssuers";
private static final String MDC_PROP_DOWNLOAD_ISSUERS_COUNTRY = "downloadedIssuersCountry";

/**
* TrustedIssuer List all issuers.
*/
@CertificateAuthenticationRequired
@GetMapping(path = "", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(
security = {
@SecurityRequirement(name = OpenApiConfig.SECURITY_SCHEMA_HASH),
@SecurityRequirement(name = OpenApiConfig.SECURITY_SCHEMA_DISTINGUISH_NAME)
},
summary = "Returns the full list of trusted issuers.",
tags = {"Trusted Issuer"},
responses = {
@ApiResponse(
responseCode = "200",
description = "Returns the full list of trusted issuers.",
content = @Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
array = @ArraySchema(schema = @Schema(implementation = TrustedIssuerDto.class)))),
@ApiResponse(
responseCode = "401",
description = "Unauthorized. No Access to the system."
+ "(Client Certificate not present or whitelisted)",
content = @Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ProblemReportDto.class)
))
})
public ResponseEntity<List<TrustedIssuerDto>> getTrustedIssuers(
@RequestAttribute(CertificateAuthenticationFilter.REQUEST_PROP_COUNTRY) String downloaderCountryCode
) {
List<TrustedIssuerDto> trustedIssuers =
trustedIssuerMapper.trustedIssuerEntityToTrustedIssuerDto(trustedIssuerService.getAllIssuers());

DgcMdc.put(MDC_PROP_DOWNLOAD_ISSUERS_COUNT, trustedIssuers.size());
DgcMdc.put(MDC_PROP_DOWNLOAD_ISSUERS_COUNTRY, downloaderCountryCode);

return ResponseEntity.ok(trustedIssuers);
}

/**
* TrustedIssuer List all issuers by country.
*/
@CertificateAuthenticationRequired
@GetMapping(path = "/{country}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(
security = {
@SecurityRequirement(name = OpenApiConfig.SECURITY_SCHEMA_HASH),
@SecurityRequirement(name = OpenApiConfig.SECURITY_SCHEMA_DISTINGUISH_NAME)
},
summary = "Returns the list of trusted issuers by country.",
tags = {"Trusted Issuer"},
responses = {
@ApiResponse(
responseCode = "200",
description = "Returns the list of trusted issuers by country.",
content = @Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
array = @ArraySchema(schema = @Schema(implementation = TrustedIssuerDto.class)))),
@ApiResponse(
responseCode = "401",
description = "Unauthorized. No Access to the system."
+ "(Client Certificate not present or whitelisted)",
content = @Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ProblemReportDto.class)
))
})
public ResponseEntity<List<TrustedIssuerDto>> getTrustedIssuersByCountry(
@RequestAttribute(CertificateAuthenticationFilter.REQUEST_PROP_COUNTRY) String downloaderCountryCode,
@PathVariable("country") String requestedCountry
) {
List<TrustedIssuerDto> trustedIssuers =
trustedIssuerMapper.trustedIssuerEntityToTrustedIssuerDto(
trustedIssuerService.getAllIssuers(requestedCountry));

DgcMdc.put(MDC_PROP_DOWNLOAD_ISSUERS_COUNT, trustedIssuers.size());
DgcMdc.put(MDC_PROP_DOWNLOAD_ISSUERS_COUNTRY, downloaderCountryCode);

return ResponseEntity.ok(trustedIssuers);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package eu.europa.ec.dgc.gateway.restapi.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.ZonedDateTime;
import lombok.Getter;
import lombok.Setter;


@Getter
@Setter
public class TrustedIssuerDto {

@Schema(example = "https://url")
private String url;

@Schema(example = "HTTP")
private UrlTypeDto type;

@Schema(example = "EU")
private String country;

@Schema(example = "aaba14fa10c3a2fb441a28af0ec1bb4128153b9ddc796b66bfa04b02ea3e103e")
private String thumbprint;

@Schema(example = "o53CbAa77LyIMFc5Gz+B2Jc275Gdg/SdLayw7gx0GrTcinR95zfTLr8nNHgJMYlX3rD8Y11zB/Osyt0 ..."
+ " W+VIrYRGSEmgjGy2EwzvA5nVhsaA+/udnmbyQw9LjAOQ==")
private String sslPublicKey;

@Schema(example = "JWKS")
private String keyStorageType;

@Schema(example = "o53CbAa77LyIMFc5Gz+B2Jc275Gdg/SdLayw7gx0GrTcinR95zfTLr8nNHgJMYlX3rD8Y11zB/Osyt0 ..."
+ " W+VIrYRGSEmgjGy2EwzvA5nVhsaA+/udnmbyQw9LjAOQ==")
private String signature;

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
private ZonedDateTime timestamp;

public enum UrlTypeDto {
HTTP,
DID
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package eu.europa.ec.dgc.gateway.restapi.mapper;

import eu.europa.ec.dgc.gateway.entity.TrustedIssuerEntity;
import eu.europa.ec.dgc.gateway.restapi.dto.TrustedIssuerDto;
import java.util.List;
import org.mapstruct.Mapper;


@Mapper(componentModel = "spring")
public interface GwTrustedIssuerMapper {

TrustedIssuerDto trustedIssuerEntityToTrustedIssuerDto(TrustedIssuerEntity trustedIssuer);

List<TrustedIssuerDto> trustedIssuerEntityToTrustedIssuerDto(List<TrustedIssuerEntity> trustedIssuer);
}
Loading

0 comments on commit 85ff8f2

Please sign in to comment.