aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas <>2022-11-17 07:30:50 +0100
committerThomas <>2022-11-17 07:30:50 +0100
commit9a1f7840c63b7a6f584a22ea64818fe5f87fc0aa (patch)
treea7a8e0fbb2f01c0b03868c94e020978da451e196
parentd635106892599a65fe663a2c27118f7936d2359d (diff)
downloadNational_eIDAS_Gateway-9a1f7840c63b7a6f584a22ea64818fe5f87fc0aa.tar.gz
National_eIDAS_Gateway-9a1f7840c63b7a6f584a22ea64818fe5f87fc0aa.tar.bz2
National_eIDAS_Gateway-9a1f7840c63b7a6f584a22ea64818fe5f87fc0aa.zip
feat(proxyservice): add healthcheck for IDA metadata provider
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthHealthCheck.java80
-rw-r--r--modules/authmodule_id-austria/src/main/resources/spring/id_austria_auth.beans.xml3
-rw-r--r--modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthHealthCheckTest.java130
3 files changed, 213 insertions, 0 deletions
diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthHealthCheck.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthHealthCheck.java
new file mode 100644
index 00000000..5e1d889e
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthHealthCheck.java
@@ -0,0 +1,80 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.utils;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.commons.lang3.StringUtils;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.actuate.health.Health;
+import org.springframework.boot.actuate.health.HealthIndicator;
+
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+/**
+ * Spring Actuator HealthCheck for ID Austria client that evaluates the current status of
+ * ID Austria SAML2 metadata that are loaded into MS-ProxyService.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class IdAustriaAuthHealthCheck implements HealthIndicator {
+
+ private static final int DEADLINE = 3;
+
+ @Autowired IConfiguration authConfig;
+ @Autowired IdAustriaAuthMetadataProvider metadataService;
+
+ @Override
+ public Health health() {
+ String msNodeEntityID = authConfig.getBasicConfiguration(
+ IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_METADATAURL);
+
+ if (StringUtils.isEmpty(msNodeEntityID)) {
+ log.trace("No ID Austria EntityId in configuration. Skipping tests ... ");
+ return Health.unknown().build();
+
+ }
+
+ CompletableFuture<Health> asynchTestOperation = new CompletableFuture<>();
+ Executors.newCachedThreadPool().submit(() -> runConnectionTest(asynchTestOperation, msNodeEntityID));
+ try {
+ return asynchTestOperation.get(DEADLINE, TimeUnit.SECONDS);
+
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ log.info("Receive no respose from Health-Check after {} seconds.", DEADLINE);
+ return Health.outOfService().withException(e).build();
+
+ }
+
+
+ }
+
+
+ private void runConnectionTest(CompletableFuture<Health> completableFuture, String entityId) {
+ try {
+ EntityDescriptor connectorMetadata =
+ metadataService.getEntityDescriptor(entityId);
+ if (connectorMetadata != null) {
+ completableFuture.complete(Health.up().build());
+
+ } else {
+ completableFuture.complete(Health.outOfService().withDetail("Reason", "No SAML2 metadata").build());
+
+ }
+
+ } catch (ResolverException e) {
+ completableFuture.complete(Health.down(e).build());
+
+ }
+
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/main/resources/spring/id_austria_auth.beans.xml b/modules/authmodule_id-austria/src/main/resources/spring/id_austria_auth.beans.xml
index d2d16bf9..176e5424 100644
--- a/modules/authmodule_id-austria/src/main/resources/spring/id_austria_auth.beans.xml
+++ b/modules/authmodule_id-austria/src/main/resources/spring/id_austria_auth.beans.xml
@@ -28,6 +28,9 @@
<bean id="idAustriaAuthMetadataProvider"
class="at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthMetadataProvider" />
+
+ <bean id="idAustriaAuthMetadataHealth"
+ class="at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthHealthCheck" />
<!-- bean id="eidasAuthHealthCheck"
class="at.gv.egiz.eid.authhandler.modules.auth.eidas.utils.EidasCentralAuthHealthCheck" /-->
diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthHealthCheckTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthHealthCheckTest.java
new file mode 100644
index 00000000..9856ca73
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthHealthCheckTest.java
@@ -0,0 +1,130 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test.utils;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.actuate.health.Health;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.w3c.dom.Element;
+
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthHealthCheck;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthMetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+import net.shibboleth.utilities.java.support.xml.SerializeSupport;
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+import okhttp3.HttpUrl;
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_test.xml",
+ "/spring/SpringTest-context_basic_mapConfig.xml"
+})
+public class IdAustriaAuthHealthCheckTest {
+
+ @Autowired private IdAustriaAuthHealthCheck toCheck;
+ @Autowired protected MsConnectorDummyConfigMap config;
+ @Autowired private IPvp2CredentialProvider credentialProvider;
+ @Autowired IdAustriaAuthMetadataProvider provider;
+
+ private static MockWebServer mockWebServer;
+ private static HttpUrl mockServerUrl;
+
+ /**
+ * JUnit class initializer.
+ *
+ * @throws Exception In case of an OpenSAML3 initialization error
+ */
+ @BeforeClass
+ public static void classInitializer() throws Exception {
+ EaafOpenSaml3xInitializer.eaafInitialize();
+
+ mockWebServer = new MockWebServer();
+ mockServerUrl = mockWebServer.url("/sp/metadata");
+
+ }
+
+ @Test
+ public void notActive() {
+ //set-up test
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_METADATAURL,
+ null);
+
+ //perform check
+ Health status = toCheck.health();
+
+ //evaluate status
+ Assert.assertEquals("wrong status", Health.unknown().build().getStatus(), status.getStatus());
+
+ }
+
+ @Test
+ public void success() throws SamlSigningException, CredentialsNotAvailableException,
+ XMLParserException, UnmarshallingException, MarshallingException {
+
+ //set-up test
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_METADATAURL,
+ mockServerUrl.url().toString());
+ injectValidHttpMetadata(mockServerUrl.url().toString());
+
+ //perform check
+ Health status = toCheck.health();
+
+ //evaluate status
+ Assert.assertEquals("wrong status", Health.up().build().getStatus(), status.getStatus());
+
+ }
+
+ @Test
+ public void invalid() throws SamlSigningException, CredentialsNotAvailableException,
+ XMLParserException, UnmarshallingException, MarshallingException, ResolverException {
+ //set-up test
+ provider.clear();
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_METADATAURL,
+ "http://localhost:1234/junit/metadata");
+
+ //perform check
+ Health status = toCheck.health();
+
+ //evaluate status
+ Assert.assertEquals("wrong status", Health.outOfService().build().getStatus(), status.getStatus());
+
+ }
+
+ private String injectValidHttpMetadata(String dynEntityId) throws XMLParserException,
+ UnmarshallingException, MarshallingException, SamlSigningException, CredentialsNotAvailableException {
+ final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ IdAustriaAuthHealthCheckTest.class.getResourceAsStream("/data/idp_metadata_no_sig.xml"));
+ metadata.setValidUntil(Instant.now().plus(1, ChronoUnit.DAYS));
+ metadata.setSignature(null);
+ metadata.setEntityID(dynEntityId);
+ Saml2Utils.signSamlObject(metadata, credentialProvider.getMetaDataSigningCredential(), true);
+ final Element metadataElement = XMLObjectSupport.marshall(metadata);
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(SerializeSupport.nodeToString(metadataElement))
+ .setHeader("Content-Type", "text/html;charset=utf-8"));
+ return dynEntityId;
+
+}
+
+}