Skip to content

Commit

Permalink
Rework fitConnect config
Browse files Browse the repository at this point in the history
  • Loading branch information
zechmeister committed Oct 29, 2024
1 parent a3c5b6c commit 264c05e
Show file tree
Hide file tree
Showing 15 changed files with 177 additions and 61 deletions.
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ lefthook-local.yml
### macOS ###
.DS_Store

fitConnectConfig.yaml
!fitConnectConfig.yaml.example
!**/test/resources/fitConnectConfig.yaml
### fit-connect ###
signing_key.json
decryption_key.json
application-local.yaml
Original file line number Diff line number Diff line change
@@ -1,28 +1,81 @@
package de.bund.digitalservice.a2j.config;

import com.nimbusds.jose.jwk.JWK;
import dev.fitko.fitconnect.api.config.ApplicationConfig;
import dev.fitko.fitconnect.api.config.SenderConfig;
import dev.fitko.fitconnect.api.config.SubscriberConfig;
import dev.fitko.fitconnect.api.config.defaults.Environments;
import dev.fitko.fitconnect.client.SenderClient;
import dev.fitko.fitconnect.client.bootstrap.ApplicationConfigLoader;
import dev.fitko.fitconnect.client.SubscriberClient;
import dev.fitko.fitconnect.client.bootstrap.ClientFactory;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.ClassPathResource;

@Configuration
public class FitConnectConfig {
private final ResourceLoader resourceLoader;
@Value("${fitConnect.sender.clientId}")
String senderClientId;

public FitConnectConfig(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Value("${fitConnect.sender.clientSecret}")
String senderClientSecret;

@Value("${fitConnect.subscriber.clientId}")
String subscriberClientId;

@Value("${fitConnect.subscriber.clientSecret}")
String subscriberClientSecret;

@Value("${fitConnect.subscriber.privateDecryptionKeyPath}")
String subscriberPrivateDecryptionKeyPath;

@Value("${fitConnect.subscriber.privateSigningKeyPath}")
String subscriberPrivateSigningKeyPath;

@Bean
public SenderClient senderClient() throws IOException {
public SenderClient senderClient() {
SenderConfig senderConfig =
SenderConfig.builder().clientId(senderClientId).clientSecret(senderClientSecret).build();

ApplicationConfig config =
ApplicationConfigLoader.loadConfigFromPath(
Path.of(resourceLoader.getResource("classpath:fitConnectConfig.yaml").getURI()));
ApplicationConfig.builder()
.senderConfig(senderConfig)
.activeEnvironment(Environments.TEST.getEnvironmentName())
.build();

return ClientFactory.createSenderClient(config);
}

@Bean
public SubscriberClient subscriberClient() throws IOException, ParseException {
SubscriberConfig subscriberConfig =
SubscriberConfig.builder()
.clientId(subscriberClientId)
.clientSecret(subscriberClientSecret)
.privateDecryptionKeys(List.of(loadKey(subscriberPrivateDecryptionKeyPath)))
.privateSigningKey(loadKey(subscriberPrivateSigningKeyPath))
.build();

ApplicationConfig config =
ApplicationConfig.builder()
.subscriberConfig(subscriberConfig)
.activeEnvironment(Environments.TEST.getEnvironmentName())
.build();

return ClientFactory.createSubscriberClient(config);
}

private JWK loadKey(String filePath) throws IOException, ParseException {
Path path = Paths.get(new ClassPathResource(filePath).getURI());
String jwkContent = Files.readString(path);

return JWK.parse(jwkContent);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package de.bund.digitalservice.a2j.config;

import de.bund.digitalservice.a2j.service.receiver.CallbackVerificationFilter;
import de.bund.digitalservice.a2j.service.subscriber.CallbackVerificationFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package de.bund.digitalservice.a2j.controller;

import de.bund.digitalservice.a2j.service.subscriber.SubscriberService;
import dev.fitko.fitconnect.api.domain.model.submission.SubmissionForPickup;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SubscriberController {

private final SubscriberService service;

public SubscriberController(SubscriberService service) {
this.service = service;
}

@PostMapping("callbacks/fit-connect")
public void newSubmission(@RequestBody SubmissionForPickup submission) {
service.pickUpSubmission(submission);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import dev.fitko.fitconnect.client.SenderClient;
import java.net.URI;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

Expand All @@ -16,13 +18,14 @@ public class FitConnectSenderService implements SenderService {
private final String serviceUrn;
private final String serviceName;
private final String jsonUri;
private final Logger logger = LoggerFactory.getLogger(FitConnectSenderService.class);

public FitConnectSenderService(
SenderClient senderClient,
@Value("${submission.destination}") String destinationUuid,
@Value("${submission.serviceType.urn}") String serviceUrn,
@Value("${submission.serviceType.name}") String serviceName,
@Value("${submission.jsonUri}") String jsonUri) {
@Value("${fitConnect.submission.destination}") String destinationUuid,
@Value("${fitConnect.submission.serviceType.urn}") String serviceUrn,
@Value("${fitConnect.submission.serviceType.name}") String serviceName,
@Value("${fitConnect.submission.jsonUri}") String jsonUri) {
this.client = senderClient;
this.destinationUuid = destinationUuid;
this.serviceUrn = serviceUrn;
Expand All @@ -42,8 +45,10 @@ public String submit(SubmitRequest submitRequest) {

try {
SentSubmission sentSubmission = client.send(submission);
logger.info("Submission sent, caseId: " + sentSubmission.getCaseId());
return "submission sent, caseId: " + sentSubmission.getCaseId();
} catch (FitConnectSenderException e) {
logger.error("failed to submit request: " + e.getMessage());
return "failed to submit: " + e.getMessage();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package de.bund.digitalservice.a2j.service.receiver;
package de.bund.digitalservice.a2j.service.subscriber;

import dev.fitko.fitconnect.client.SenderClient;
import jakarta.servlet.FilterChain;
Expand All @@ -7,6 +7,8 @@
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
Expand All @@ -15,9 +17,10 @@
public class CallbackVerificationFilter extends OncePerRequestFilter {
private final SenderClient senderClient;
private final String callbackSecret;
private final Logger logger = LoggerFactory.getLogger(CallbackVerificationFilter.class);

public CallbackVerificationFilter(
SenderClient senderClient, @Value("${callbackSecret}") String callbackSecret) {
SenderClient senderClient, @Value("${fitConnect.callbackSecret}") String callbackSecret) {
this.senderClient = senderClient;
this.callbackSecret = callbackSecret;
}
Expand All @@ -40,7 +43,7 @@ protected void doFilterInternal(
callbackSecret)
.isValid()) {

System.out.println("Received fit-connect callback, returned 401");
logger.info("Received invalid fit-connect callback");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package de.bund.digitalservice.a2j.service.subscriber;

import dev.fitko.fitconnect.api.domain.model.submission.SubmissionForPickup;
import dev.fitko.fitconnect.api.domain.subscriber.ReceivedSubmission;
import dev.fitko.fitconnect.client.SubscriberClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class FitConnectSubscriberService implements SubscriberService {

private final SubscriberClient client;
private static final Logger logger = LoggerFactory.getLogger(FitConnectSubscriberService.class);

public FitConnectSubscriberService(SubscriberClient client) {
this.client = client;
}

public void pickUpSubmission(SubmissionForPickup submissionForPickup) {
ReceivedSubmission receivedSubmission = client.requestSubmission(submissionForPickup);
logger.info("Submission requested. SubmissionId: " + submissionForPickup.getSubmissionId());

receivedSubmission.acceptSubmission();
logger.info("Submission accepted. CaseId: " + receivedSubmission.getCaseId());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package de.bund.digitalservice.a2j.service.subscriber;

import dev.fitko.fitconnect.api.domain.model.submission.SubmissionForPickup;

public interface SubscriberService {

void pickUpSubmission(SubmissionForPickup submissionForPickup);
}
8 changes: 0 additions & 8 deletions src/main/resources/application-local.yaml

This file was deleted.

17 changes: 17 additions & 0 deletions src/main/resources/application-local.yaml.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
fitConnect:
sender:
clientId: senderClientId
clientSecret: s3cr3t
subscriber:
clientId: subscriberClientId
clientSecret: s3cr3t
privateDecryptionKeyPath: decryption_key.json
privateSigningKeyPath: signing_key.json
activeEnvironment: TEST
submission:
destination: destinationId
serviceType:
urn: urn:de:fim:leika:leistung:99400048079000
name: Simple Dummy Service
jsonUri: https://schema.fitko.de/fim/s17000717_1.0.schema.json
callbackSecret: s3cr3t
5 changes: 0 additions & 5 deletions src/main/resources/fitConnectConfig.yaml.example

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ void senderAndReceiverClassesShouldBeIndependent() {
.resideInAPackage("de.bund.digitalservice.a2j.service.sender..")
.should()
.dependOnClassesThat()
.resideInAnyPackage("de.bund.digitalservice.a2j.service.receiver..")
.resideInAnyPackage("de.bund.digitalservice.a2j.service.subscriber..")
.check(classes);

ArchRuleDefinition.noClasses()
.that()
.resideInAPackage("de.bund.digitalservice.a2j.service.receiver..")
.resideInAPackage("de.bund.digitalservice.a2j.service.subscriber..")
.should()
.dependOnClassesThat()
.resideInAnyPackage("de.bund.digitalservice.a2j.service.sender..")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class ReceiverIntegrationTest {
@Autowired private MockMvc mockMvc;

@Test
void shouldExposeCallback() throws Exception {
mockMvc.perform(post("/callbacks/fit-connect")).andExpect(status().isOk());
void shouldSecureCallbackWithoutAuthorization() throws Exception {
mockMvc.perform(post("/callbacks/fit-connect")).andExpect(status().is4xxClientError());
}
}
25 changes: 17 additions & 8 deletions src/test/resources/application-test.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
submission:
destination: d0fe1fad-erf3-4c67-123i-9d0ca6663bf3
serviceType:
urn: urn:de:fim:leika:leistung:99400048079112
name: Simple Dummy Service
jsonUri: https://schema.fitko.de/fim/s170007g_1.0.schema.json

callbackSecret: s3cr3t
fitConnect:
sender:
clientId: senderClientId
clientSecret: s3cr3t
subscriber:
clientId: subscriberClientId
clientSecret: s3cr3t
privateDecryptionKeyPath: decryption_key.json
privateSigningKeyPath: signing_key.json
activeEnvironment: TEST
submission:
destination: destinationId
serviceType:
urn: urn:de:fim:leika:leistung:99400048079000
name: Simple Dummy Service
jsonUri: https://schema.fitko.de/fim/s17000717_1.0.schema.json
callbackSecret: s3cr3t

0 comments on commit 264c05e

Please sign in to comment.