Skip to content

Commit

Permalink
EPA-145: Updated fedreg command to handle PU format
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasrichner-oviva committed Sep 6, 2024
1 parent 3bb555a commit 0f373a2
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 22 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ Use environment variables to configure the relying party server.
| `EHEALTHID_RP_HOST` | Host to bind to. | `0.0.0.0` |
| `EHEALTHID_RP_PORT` | Port to bind to. | `1234` |
| `EHEALTHID_RP_ES_TTL` | The time to live for the entity statement. In ISO8601 format. | `PT12H` |
| `EHEALTHID_RP_SCOPES` | The comma separated list of scopes requested in the federation. This __MUST__ match what was registered with the federation master. | `openid,urn:telematik:email,urn:telematik:display_name` |
| `EHEALTHID_RP_SCOPES` | The comma separated list of scopes requested in the federation. This __MUST__ match what was registered with the federation master. | `openid,urn:telematik:versicherter` |
| `EHEALTHID_RP_SESSION_STORE_TTL` | The time to live for sessions. In ISO8601 format. | `PT20M` |
| `EHEALTHID_RP_SESSION_STORE_MAX_ENTRIES` | The maximum number of sessions to store. Keeps memory bounded. | `1000` |
| `EHEALTHID_RP_CODE_STORE_TTL` | The time to live for codes, i.e. successful logins where the code is not redeemed yet. In ISO8601 format. | `PT5M` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,13 @@ public class FedRegistrationCommand implements Callable<Integer> {

@Option(
names = {"-c", "--contact-email"},
description = "the technical contact email for the IdP",
required = true)
private String email;
description = "the technical contact email for the IdP")
private String contactEmail;

@Option(
names = {"--vfs-confirmation"},
description = "gematik-Verfahrensschlüssel (starts with VFS_DiGA_...)")
private String vfsConfirmation;

public static void main(String[] args) {

Expand All @@ -83,6 +87,8 @@ public static void main(String[] args) {

public Integer call() throws Exception {

parameterValidation();

var entityConfiguration = fetchEntityConfiguration();
for (var key : entityConfiguration.jwks().getKeys()) {
validateKey(key, KeyUse.SIGNATURE);
Expand All @@ -97,28 +103,43 @@ public Integer call() throws Exception {
return 0;
}

private void printRegistrationForm(EntityConfiguration entityConfiguration) {
var registrationForm = renderRegistrationForm(entityConfiguration);
System.out.println(registrationForm);
}

private void writeRegistrationForm(EntityConfiguration entityConfiguration) throws IOException {
var registrationForm = renderRegistrationForm(entityConfiguration);

logger.atInfo().log("writing registration form to '{}'", file);
Files.writeString(file, registrationForm);
}

private String renderRegistrationForm(EntityConfiguration entityConfiguration) {
return RegistratonFormRenderer.render(
new Model(
vfsConfirmation,
memberId,
entityConfiguration.orgName(),
email,
contactEmail,
issuerUri,
environment,
entityConfiguration.scopes(),
entityConfiguration.jwks()));
}

private void printRegistrationForm(EntityConfiguration entityConfiguration) {
var registrationForm = renderRegistrationForm(entityConfiguration);
System.out.println(registrationForm);
}

private void writeRegistrationForm(EntityConfiguration entityConfiguration) throws IOException {
var registrationForm = renderRegistrationForm(entityConfiguration);

logger.atInfo().log("writing registration form to '{}'", file);
Files.writeString(file, registrationForm);
private void parameterValidation() {
if (environment == Environment.PU) {
if (vfsConfirmation == null || vfsConfirmation.isBlank()) {
logger.atError().log("Verfahrensschlüssel is required for production (PU) environment");
throw new RuntimeException();
}
} else {
if (contactEmail == null || contactEmail.isBlank()) {
logger.atError().log("contact email is required for test environments");
throw new RuntimeException();
}
}
}

private EntityConfiguration fetchEntityConfiguration() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,39 @@

public class RegistratonFormRenderer {

private static final String XML_TEMPLATE =
private static final String XML_TEMPLATE_PROD =
"""
<?xml version="1.0" encoding="UTF-8"?>
<registrierungtifoederation>
<datendesantragstellers>
<vfsbestaetigung>{{vfsConfirmation}}</vfsbestaetigung>
<teilnehmertyp>Fachdienst</teilnehmertyp>
<organisationsname>{{organisationName}}</organisationsname>
<memberid>{{memberId}}</memberid>
<zwg>ORG-0001:BT-0144</zwg>
<issueruri>{{issuerUri}}</issueruri>
<scopes>
<scopealter>{{scopeAge}}</scopealter>
<scopeanzeigename>{{scopeDisplayName}}</scopeanzeigename>
<scopeemail>{{scopeEmail}}</scopeemail>
<scopegeschlecht>{{scopeGender}}</scopegeschlecht>
<scopegeburtsdatum>{{scopeDateOfBirth}}</scopegeburtsdatum>
<scopevorname>{{scopeFirstName}}</scopevorname>
<scopenachname>{{scopeLastName}}</scopenachname>
<scopeversicherter>{{scopeInsuredPerson}}</scopeversicherter>
</scopes>
{{#publicKeys}}
<publickeys>
<kidjwt>{{kid}}</kidjwt>
<pubkeyjwt>{{pem}}</pubkeyjwt>
<betriebsumgebung>{{environment}}</betriebsumgebung>
</publickeys>
{{/publicKeys}}
</datendesantragstellers>
</registrierungtifoederation>
""";

private static final String XML_TEMPLATE_TEST =
"""
<?xml version="1.0" encoding="UTF-8"?>
<registrierungtifoederation>
Expand Down Expand Up @@ -48,17 +80,34 @@ public class RegistratonFormRenderer {

public static String render(Model m) {

return switch (m.environment()) {
case PU -> renderProductive(m);
default -> renderTestEnvironment(m);
};
}

private static String renderProductive(Model m) {
return renderTemplate(XML_TEMPLATE_PROD, m);
}

private static String renderTestEnvironment(Model m) {
return renderTemplate(XML_TEMPLATE_TEST, m);
}

private static String renderTemplate(String template, Model m) {

var mf = new DefaultMustacheFactory();
var template = mf.compile(new StringReader(XML_TEMPLATE), "entity-statement-registration");
var compiledTemplate = mf.compile(new StringReader(template), "entity-statement-registration");

var w = new StringWriter();

var rm = RenderModel.fromModel(m);
template.execute(w, rm);
compiledTemplate.execute(w, rm);
return w.toString();
}

public record Model(
String vfsConfirmation,
String memberId,
String organisationName,
String contactEmail,
Expand Down Expand Up @@ -87,6 +136,7 @@ enum Scope {
}

record RenderModel(
String vfsConfirmation,
String memberId,
String organisationName,
String issuerUri,
Expand All @@ -105,6 +155,7 @@ record RenderModel(
public static RenderModel fromModel(Model m) {

return new RenderModel(
m.vfsConfirmation(),
m.memberId(),
m.organisationName(),
m.issuerUri().toString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ void render() throws JOSEException {
var xml =
RegistratonFormRenderer.render(
new Model(
"VFS_DiGA_Test",
"FDmyDiGAMemb",
"My DiGA",
"[email protected]",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,7 @@ private List<String> getScopes() {

return configProvider
.get(CONFIG_SCOPES)
.or(
() ->
Optional.of(
"openid,urn:telematik:email,urn:telematik:versicherter,urn:telematik:display_name"))
.or(() -> Optional.of("openid,urn:telematik:versicherter"))
.stream()
.flatMap(Strings::mustParseCommaList)
.toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class GematikHeaderDecoratorHttpClient implements HttpClient {
LoggerFactory.getLogger(GematikHeaderDecoratorHttpClient.class);

// RU: https://gsi-ref.dev.gematik.solutions/.well-known/openid-federation
// RU PAR mTLS: https://gsi-ref-mtls.dev.gematik.solutions/PAR_Auth
// TU: https://gsi.dev.gematik.solutions/.well-known/openid-federation
private static final Pattern HOST_GEMATIK_IDP =
Pattern.compile("gsi(-[-a-z0-9]+)?.dev.gematik.solutions");
Expand Down

0 comments on commit 0f373a2

Please sign in to comment.