[java-idp-plugin-metadatagen] branch dev/JMETAGEN-5 updated: JMETAGEN-5 - Replacement for SP metagen script
Scott Cantor
cantor.2 at osu.edu
Mon Jul 10 19:18:24 UTC 2023
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch dev/JMETAGEN-5
in repository java-idp-plugin-metadatagen.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-plugin-metadatagen.git;a=commit;h=13d95c853def4d883e2aa6bfe260cfab57fd615f
The following commit(s) were added to refs/heads/dev/JMETAGEN-5 by this push:
new 13d95c8 JMETAGEN-5 - Replacement for SP metagen script
13d95c8 is described below
commit 13d95c853def4d883e2aa6bfe260cfab57fd615f
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon Jul 10 15:18:22 2023 -0400
JMETAGEN-5 - Replacement for SP metagen script
https://shibboleth.atlassian.net/browse/JMETAGEN-5
Refactor generic code into OpenSAML.
---
metadatagen-impl/pom.xml | 17 +
.../impl/AssertionConsumerServiceConverter.java | 55 +++
.../plugin/metadatagen/impl/MetadataGenCLI.java | 85 ++--
.../impl/MetadataGenCommandLineArguments.java | 520 +++++++--------------
.../impl/SingleLogoutServiceConverter.java | 61 +++
.../AttributeAuthorityDescriptor.vm | 3 -
.../metadatagen-templates/EntityDescriptor.vm | 13 -
.../metadatagen-templates/IDPSSODescriptor.vm | 4 -
.../metadatagen-templates/KeyDescriptors.vm | 30 --
.../metadatagen-templates/SPSSODescriptor.vm | 18 -
.../metadatagen-templates/SingleLogoutServices.vm | 12 -
.../idp/plugin/metadatagen/conf/velocity.xml | 3 +
.../plugin/metadatagen/impl/MetadataGenTest.java | 85 +---
13 files changed, 345 insertions(+), 561 deletions(-)
diff --git a/metadatagen-impl/pom.xml b/metadatagen-impl/pom.xml
index 0fab6c1..dc0b8a8 100644
--- a/metadatagen-impl/pom.xml
+++ b/metadatagen-impl/pom.xml
@@ -47,11 +47,28 @@
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>${shib-shared.groupId}</groupId>
+ <artifactId>shib-profile-impl</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${shib-shared.groupId}</groupId>
+ <artifactId>shib-metadata-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
<dependency>
<groupId>${opensaml.groupId}</groupId>
<artifactId>opensaml-saml-api</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>${opensaml.groupId}</groupId>
+ <artifactId>opensaml-saml-impl</artifactId>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>${opensaml.groupId}</groupId>
<artifactId>opensaml-security-api</artifactId>
diff --git a/metadatagen-impl/src/main/java/net/shibboleth/idp/plugin/metadatagen/impl/AssertionConsumerServiceConverter.java b/metadatagen-impl/src/main/java/net/shibboleth/idp/plugin/metadatagen/impl/AssertionConsumerServiceConverter.java
new file mode 100644
index 0000000..087f059
--- /dev/null
+++ b/metadatagen-impl/src/main/java/net/shibboleth/idp/plugin/metadatagen/impl/AssertionConsumerServiceConverter.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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.
+ */
+
+package net.shibboleth.idp.plugin.metadatagen.impl;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
+
+import net.shibboleth.idp.cas.config.AbstractProtocolConfiguration;
+import net.shibboleth.shared.annotation.constraint.Live;
+import net.shibboleth.shared.collection.Pair;
+
+/**
+ * JCommander support for parsing a binding/endpoint pair into a {@link AssertionConsumerService}.
+ */
+public class AssertionConsumerServiceConverter extends org.opensaml.saml.metadata.generator.impl.AssertionConsumerServiceConverter {
+
+ /** {@inheritDoc} */
+ @Nonnull public AssertionConsumerService apply(@Nullable final String value,
+ @Nullable @Live final List<String> protocols) {
+ return getProcessedEndpoint(protocols, value);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull protected Pair<String,String> getProtocolAndBinding(@Nonnull final String input) {
+ if (input.startsWith("CAS/")) {
+ return new Pair<>(AbstractProtocolConfiguration.PROTOCOL_URI,
+ AbstractProtocolConfiguration.PROTOCOL_URI + "/login");
+ } else if (input.startsWith("CASProxy/")) {
+ return new Pair<>(AbstractProtocolConfiguration.PROTOCOL_URI,
+ AbstractProtocolConfiguration.PROTOCOL_URI + "/proxy");
+ }
+ return super.getProtocolAndBinding(input);
+ }
+
+}
\ No newline at end of file
diff --git a/metadatagen-impl/src/main/java/net/shibboleth/idp/plugin/metadatagen/impl/MetadataGenCLI.java b/metadatagen-impl/src/main/java/net/shibboleth/idp/plugin/metadatagen/impl/MetadataGenCLI.java
index 08ed7e6..b4080a6 100644
--- a/metadatagen-impl/src/main/java/net/shibboleth/idp/plugin/metadatagen/impl/MetadataGenCLI.java
+++ b/metadatagen-impl/src/main/java/net/shibboleth/idp/plugin/metadatagen/impl/MetadataGenCLI.java
@@ -21,9 +21,9 @@ import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.io.PrintWriter;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
+import java.io.Writer;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
@@ -37,9 +37,7 @@ import java.util.stream.Stream;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
-import org.apache.velocity.context.Context;
import org.opensaml.core.xml.LangBearing;
import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.ext.reqattr.RequestedAttributes;
@@ -47,6 +45,8 @@ import org.opensaml.saml.ext.saml2mdui.Description;
import org.opensaml.saml.ext.saml2mdui.DisplayName;
import org.opensaml.saml.ext.saml2mdui.Logo;
import org.opensaml.saml.ext.saml2mdui.UIInfo;
+import org.opensaml.saml.metadata.generator.impl.AbstractEndpointConverter;
+import org.opensaml.saml.metadata.generator.impl.VelocityMetadataGenerator;
import org.opensaml.saml.saml2.core.Extensions;
import org.opensaml.saml.saml2.metadata.ArtifactResolutionService;
import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
@@ -70,7 +70,6 @@ import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
-import net.shibboleth.idp.cas.config.AbstractProtocolConfiguration;
import net.shibboleth.idp.cli.AbstractIdPHomeAwareCommandLine;
import net.shibboleth.idp.saml.xmlobject.ExtensionsConstants;
import net.shibboleth.idp.saml.xmlobject.Scope;
@@ -97,15 +96,9 @@ public final class MetadataGenCLI extends AbstractIdPHomeAwareCommandLine<Metada
/** Class logger. */
@Nullable private Logger log;
- /** Where we are outputting to? */
- private PrintWriter output;
-
/** The processed arguments. */
private MetadataGenCommandLineArguments args;
- /** Velocity engine for output generation. */
- private VelocityEngine velocityEngine;
-
/** Constructor. */
public MetadataGenCLI() {
setCaseSensitiveOptions(false);
@@ -481,49 +474,23 @@ public final class MetadataGenCLI extends AbstractIdPHomeAwareCommandLine<Metada
}
/**
- * Builds the Velocity template context.
- *
- * @return the populated context
- */
- @Nonnull private VelocityContext getVelocityContext() {
- final VelocityContext context = new VelocityContext();
-
- context.put("args", args);
-
- // Namespace handling.
- if (!args.isOmitNamespaces()) {
- final Map<String,String> prefixMap = new HashMap<>();
- prefixMap.put(SAMLConstants.SAML20MD_PREFIX, SAMLConstants.SAML20MD_NS);
- prefixMap.put(SAMLConstants.SAML20_PREFIX, SAMLConstants.SAML20_NS);
- prefixMap.put(SignatureConstants.XMLSIG_PREFIX, SignatureConstants.XMLSIG_NS);
- if (args.isOIDC()) {
- prefixMap.put("oidcmd", "urn:mace:shibboleth:metadata:oidc:1.0");
- }
- context.put("namespaces", prefixMap);
- }
-
- return context;
- }
-
- /**
- * Set up {@link MetadataGenCLI#output}.
+ * Get the output sink.
*
- * @return true iff this worked
+ * @return output sink
*/
- private boolean setupWriter() {
+ @Nullable private Writer getWriter() {
if (args.getOutputFile() == null) {
- output = new PrintWriter(System.out);
+ return new PrintWriter(System.out);
} else {
final File out = new File(args.getOutputFile());
try {
final FileOutputStream outStream = new FileOutputStream(out);
- output = new PrintWriter(new BufferedOutputStream(outStream));
+ return new PrintWriter(new BufferedOutputStream(outStream));
} catch (final IOException e) {
getLogger().error("Could not open {}", args.getOutputFile(), e);
- return false;
+ return null;
}
}
- return true;
}
/** {@inheritDoc} */
@@ -535,27 +502,39 @@ public final class MetadataGenCLI extends AbstractIdPHomeAwareCommandLine<Metada
if (ret != RC_OK) {
return ret;
}
-
- if (!setupWriter()) {
- return RC_IO;
- }
-
+
+ final VelocityEngine velocityEngine;
try {
velocityEngine = getApplicationContext().getBean(VELOCITY_ENGINE_BEAN_NAME, VelocityEngine.class);
} catch (final BeansException e) {
getLogger().error("Unable to acquire Velocity engine bean", e);
return RC_INIT;
}
+
+ final Writer sink = getWriter();
+ if (sink == null) {
+ return RC_IO;
+ }
try {
- Template.fromTemplateName(velocityEngine,
- "/metadatagen-templates/EntityDescriptor.vm").merge(getVelocityContext(), output);
+ final VelocityMetadataGenerator generator = new VelocityMetadataGenerator();
+ generator.setId("MetadataGeneratorCLI");
+ generator.setVelocityEngine(velocityEngine);
+ generator.initialize();
+
+ assert args != null;
+ generator.generate(args, sink);
+ sink.close();
} catch (final Exception e) {
getLogger().error("Error generating output", e);
+ try {
+ sink.close();
+ } catch (final IOException e1) {
+
+ }
return RC_IO;
}
- output.close();
return RC_OK;
}
@@ -569,6 +548,10 @@ public final class MetadataGenCLI extends AbstractIdPHomeAwareCommandLine<Metada
* @param args arguments
*/
public static int runMain(@Nonnull final String[] args) {
+ // Add Shibboleth-specific SAML 1.1 binding.
+ AbstractEndpointConverter.addBinding("Redirect1", SAMLConstants.SAML11P_NS,
+ net.shibboleth.idp.saml.xml.SAMLConstants.SAML1_REQUEST_BINDING);
+
final MetadataGenCLI cli = new MetadataGenCLI();
return cli.run(args);
diff --git a/metadatagen-impl/src/main/java/net/shibboleth/idp/plugin/metadatagen/impl/MetadataGenCommandLineArguments.java b/metadatagen-impl/src/main/java/net/shibboleth/idp/plugin/metadatagen/impl/MetadataGenCommandLineArguments.java
index a1fc765..c9a216c 100644
--- a/metadatagen-impl/src/main/java/net/shibboleth/idp/plugin/metadatagen/impl/MetadataGenCommandLineArguments.java
+++ b/metadatagen-impl/src/main/java/net/shibboleth/idp/plugin/metadatagen/impl/MetadataGenCommandLineArguments.java
@@ -21,38 +21,52 @@ import java.io.PrintStream;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
+import java.util.Set;
+import java.util.function.BiFunction;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import org.opensaml.saml.common.xml.SAMLConstants;
-import org.opensaml.saml.saml2.metadata.ArtifactResolutionService;
-import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
-import org.opensaml.saml.saml2.metadata.AttributeService;
-import org.opensaml.saml.saml2.metadata.SingleLogoutService;
-import org.opensaml.saml.saml2.metadata.SingleSignOnService;
+import org.opensaml.core.xml.Namespace;
+import org.opensaml.core.xml.XMLObjectBuilderFactory;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.metadata.generator.impl.ArtifactResolutionServiceConverter;
+import org.opensaml.saml.metadata.generator.impl.AttributeServiceConverter;
+import org.opensaml.saml.metadata.generator.impl.SingleSignOnServiceConverter;
+import org.opensaml.saml.metadata.generator.impl.TemplateMetadataGeneratorParameters;
+import org.opensaml.saml.saml2.metadata.AttributeAuthorityDescriptor;
+import org.opensaml.saml.saml2.metadata.Endpoint;
+import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
+import org.opensaml.saml.saml2.metadata.IndexedEndpoint;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
import org.opensaml.security.x509.X509Support;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.beust.jcommander.Parameter;
+import com.google.common.base.Predicates;
-import net.shibboleth.idp.cas.config.AbstractProtocolConfiguration;
import net.shibboleth.idp.cli.AbstractIdPHomeAwareCommandLineArguments;
+import net.shibboleth.shared.annotation.constraint.Live;
import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.annotation.constraint.NotLive;
import net.shibboleth.shared.annotation.constraint.Unmodifiable;
import net.shibboleth.shared.codec.Base64Support;
import net.shibboleth.shared.codec.EncodingException;
import net.shibboleth.shared.collection.CollectionSupport;
-import net.shibboleth.shared.primitive.StringSupport;
/**
* Command line arguments for Metadata Generation.
+ *
+ * <p>Note that JCommander does not appear to handle data conversion when lists are involved,
+ * so the code is invoking a library of endpoint converters by hand.</p>
*/
-public class MetadataGenCommandLineArguments extends AbstractIdPHomeAwareCommandLineArguments {
+public class MetadataGenCommandLineArguments extends AbstractIdPHomeAwareCommandLineArguments
+ implements TemplateMetadataGeneratorParameters {
/** Property name for the back channel certificate. */
@Nonnull @NotEmpty public static final String BACKCHANNEL_PROPERTY = "idp.metadata.backchannel.cert";
@@ -84,18 +98,6 @@ public class MetadataGenCommandLineArguments extends AbstractIdPHomeAwareCommand
/** The unique ID. */
@Parameter(names = {"--entityID", "--client_id", "--id"}, required=true, description="Unique ID for entity")
@Nullable private String entityID;
-
- /** Do we output SAML 2.0? */
- @Parameter(names = {"--saml2"}, description="Include SAML 2.0 support?")
- private boolean saml2;
-
- /** Do we output CAS? */
- @Parameter(names = {"--cas"}, description="Include CAS support?")
- private boolean cas;
-
- /** Do we output OIDC? */
- @Parameter(names = {"--oidc"}, description="Include OpenID/OAuth support?")
- private boolean oidc;
/** Do we output an SP role? */
@Parameter(names = {"--sp"}, description="Include Service Provider role?")
@@ -109,44 +111,20 @@ public class MetadataGenCommandLineArguments extends AbstractIdPHomeAwareCommand
@Parameter(names = {"--aa"}, description="Include Attribute Authority role?")
private boolean aa;
- @Parameter(names = {"--sso-redirect"}, description="SingleSignOnService endpoint using HTTP-Redirect binding")
- @Nullable private String ssoRedirect;
-
- @Parameter(names = {"--sso-post"}, description="SingleSignOnService endpoint using HTTP-POST binding")
- @Nullable private String ssoPost;
-
- @Parameter(names = {"--sso-artifact"}, description="SingleSignOnService endpoint using HTTP-Artifact binding")
- @Nullable private String ssoArtifact;
-
- @Parameter(names = {"--sso-soap"}, description="SingleSignOnService endpoint using SOAP binding")
- @Nullable private String ssoSoap;
+ @Parameter(names = {"--sso"}, description="SingleSignOnService endpoint(s)")
+ @Nonnull private List<String> ssoServices = new ArrayList<>();
- @Parameter(names = {"--attr-soap"}, description="AttributeService endpoint using SOAP binding")
- @Nullable private String attributeSoap;
+ @Parameter(names = {"--attribute-query", "--query"}, description="AttributeService endpoint(s)")
+ @Nonnull private List<String> attributeServices = new ArrayList<>();
- @Parameter(names = {"--artifact-soap", "--artifact"}, description="ArtifactResolutionService endpoint(s) using SOAP binding")
- @Nonnull private List<String> artifactSoap = new ArrayList<>();
+ @Parameter(names = {"--artifact"}, description="ArtifactResolutionService endpoint(s)")
+ @Nonnull private List<String> artifactServices = new ArrayList<>();
- @Parameter(names = {"--logout-redirect", "-LR"}, description="SingleLogoutService endpoint(s) using HTTP-Redirect binding")
- @Nonnull private List<String> logoutRedirect = new ArrayList<>();
+ @Parameter(names = {"--logout", "--slo"}, description="SingleLogoutService endpoint(s)")
+ @Nonnull private List<String> logoutServices = new ArrayList<>();
- @Parameter(names = {"--logout-post", "-LP"}, description="SingleLogoutService endpoint(s) using HTTP-POST binding")
- @Nonnull private List<String> logoutPost = new ArrayList<>();
-
- @Parameter(names = {"--logout-artifact", "-LA"}, description="SingleLogoutService endpoint(s) using HTTP-Artifact binding")
- @Nonnull private List<String> logoutArtifact = new ArrayList<>();
-
- @Parameter(names = {"--logout-soap", "-LS"}, description="SingleLogoutService endpoint(s) using SOAP binding")
- @Nonnull private List<String> logoutSoap = new ArrayList<>();
-
- @Parameter(names = {"--acs", "--acs-post", "-h"}, description="AssertionConsumerService endpoint(s) using HTTP-POST binding")
- @Nonnull private List<String> acsPost = new ArrayList<>();
-
- @Parameter(names = {"--acs-artifact"}, description="AssertionConsumerService endpoint(s) using HTTP-Artifact binding")
- @Nonnull private List<String> acsArtifact = new ArrayList<>();
-
- @Parameter(names = {"--acs-paos", "--ecp"}, description="AssertionConsumerService endpoint(s) using PAOS binding")
- @Nonnull private List<String> acsPaos = new ArrayList<>();
+ @Parameter(names = {"--acs"}, description="AssertionConsumerService endpoint(s)")
+ @Nonnull private List<String> acServices = new ArrayList<>();
/** Path(s) to dual-use certificate(s). */
@Parameter(names = {"--certificate", "--cert", "-c"}, description="Path(s) to certificate(s) for signing and encryption")
@@ -177,274 +155,132 @@ public class MetadataGenCommandLineArguments extends AbstractIdPHomeAwareCommand
return entityID;
}
- /**
- * Do we output SAML 2.0 metadata?
- *
- * @return argument value
- */
- public boolean isSAML2() {
- return saml2;
- }
-
- /**
- * Do we output CAS metadata?
- *
- * @return argument value
- */
- public boolean isCAS() {
- return cas;
- }
-
- /**
- * Do we output OIDC/OAuth metadata?
- *
- * @return argument value
- */
- public boolean isOIDC() {
- return oidc;
- }
-
- /**
- * Do we output SP role?
- *
- * @return argument value
- */
- public boolean isSP() {
- return sp;
- }
-
- /**
- * Do we output IdP role?
- *
- * @return argument value
- */
- public boolean isIDP() {
- return idp;
- }
-
- /**
- * Do we output AA role?
- *
- * @return argument value
- */
- public boolean isAA() {
- return aa;
- }
-
- /**
- * Get endpoint expression for {@link SingleSignOnService} endpoints using SAML 2.0 HTTP-Redirect binding.
- *
- * <p>Endpoints may omit scheme but must specify port and full path.</p>
- *
- * @return endpoint URL
- */
- @Nullable public String getSSORedirectEndpoint() {
- return getProcessedEndpoint(ssoRedirect);
- }
+ /** {@inheritDoc} */
+ @Nullable public SPSSODescriptor getSPSSODescriptor() {
+ if (!sp) {
+ return null;
+ }
+
+ final XMLObjectBuilderFactory bf = XMLObjectProviderRegistrySupport.getBuilderFactory();
+
+ final SAMLObjectBuilder<SPSSODescriptor> builder =
+ (SAMLObjectBuilder<SPSSODescriptor>) bf.<SPSSODescriptor>ensureBuilder(
+ SPSSODescriptor.DEFAULT_ELEMENT_NAME);
+ final SPSSODescriptor role = builder.buildObject();
+
+ final List<String> protocols = new ArrayList<>();
+
+ role.getSingleLogoutServices().addAll(
+ convertEndpoints(new SingleLogoutServiceConverter(), protocols, logoutServices));
+ role.getArtifactResolutionServices().addAll(
+ convertEndpoints(new ArtifactResolutionServiceConverter(), protocols, artifactServices));
+ role.getAssertionConsumerServices().addAll(
+ convertEndpoints(new AssertionConsumerServiceConverter(), protocols, acServices));
+
+ int index = 1;
+ for (final IndexedEndpoint e : role.getArtifactResolutionServices()) {
+ e.setIndex(index++);
+ }
- /**
- * Get endpoint expression for {@link SingleSignOnService} endpoint using SAML 2.0 HTTP-POST binding.
- *
- * <p>Endpoints may omit scheme but must specify port and full path.</p>
- *
- * @return endpoint URL
- */
- @Nullable public String getSSOPostEndpoint() {
- return getProcessedEndpoint(ssoPost);
- }
-
- /**
- * Get endpoint expression for {@link SingleSignOnService} endpoint using SAML 2.0 HTTP-Artifact binding.
- *
- * <p>Endpoints may omit scheme but must specify port and full path.</p>
- *
- * @return endpoint URL
- */
- @Nullable public String getSSOArtifactEndpoint() {
- return getProcessedEndpoint(ssoArtifact);
- }
+ index = 1;
+ for (final IndexedEndpoint e : role.getAssertionConsumerServices()) {
+ e.setIndex(index++);
+ }
+
+ protocols.forEach(role::addSupportedProtocol);
- /**
- * Get endpoint expression for {@link SingleSignOnService} endpoint using SAML 2.0 SOAP binding.
- *
- * <p>Endpoints may omit scheme but must specify port and full path.</p>
- *
- * @return endpoint URL
- */
- @Nullable public String getSSOSoapEndpoint() {
- return getProcessedEndpoint(ssoSoap);
+ return role;
}
- /**
- * Get endpoint expression for {@link AttributeService} endpoint using SAML 2.0 SOAP binding.
- *
- * <p>Endpoints may omit scheme but must specify port and full path.</p>
- *
- * @return endpoint URL
- */
- @Nullable public String getAttributeSoapEndpoint() {
- return getProcessedEndpoint(attributeSoap);
- }
+ /** {@inheritDoc} */
+ @Nullable public IDPSSODescriptor getIDPSSODescriptor() {
+ if (!idp) {
+ return null;
+ }
+
+ final XMLObjectBuilderFactory bf = XMLObjectProviderRegistrySupport.getBuilderFactory();
- /**
- * Get endpoint expression for {@link ArtifactResolutionService} endpoint(s) using SAML 2.0 SOAP binding.
- *
- * <p>Endpoints may omit scheme but must specify port and full path.</p>
- *
- * @return endpoint URLs
- */
- @Nullable @Unmodifiable @NotLive public List<String> getArtifactSoapEndpoints() {
- return artifactSoap.stream()
- .map(this::getProcessedEndpoint)
- .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
- }
+ final SAMLObjectBuilder<IDPSSODescriptor> builder =
+ (SAMLObjectBuilder<IDPSSODescriptor>) bf.<IDPSSODescriptor>ensureBuilder(
+ IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
+ final IDPSSODescriptor role = builder.buildObject();
- /**
- * Get endpoint expression(s) for {@link SingleLogoutService} endpoint(s) using SAML 2.0 HTTP-Redirect binding.
- *
- * <p>Endpoints may omit scheme but must specify port and full path.</p>
- *
- * @return endpoint URLs
- */
- @Nonnull @Unmodifiable @NotLive public List<String> getLogoutRedirectEndpoints() {
- return logoutRedirect.stream()
- .map(this::getProcessedEndpoint)
- .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
- }
+ final List<String> protocols = new ArrayList<>();
- /**
- * Get endpoint expression(s) for {@link SingleLogoutService} endpoint(s) using SAML 2.0 HTTP-POST binding.
- *
- * <p>Endpoints may omit scheme but must specify port and full path.</p>
- *
- * @return endpoint URLs
- */
- @Nonnull @Unmodifiable @NotLive public List<String> getLogoutPostEndpoints() {
- return logoutPost.stream()
- .map(this::getProcessedEndpoint)
- .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
- }
+ role.getSingleLogoutServices().addAll(
+ convertEndpoints(new SingleLogoutServiceConverter(), protocols, logoutServices));
+ role.getSingleSignOnServices().addAll(
+ convertEndpoints(new SingleSignOnServiceConverter(), protocols, ssoServices));
+ role.getArtifactResolutionServices().addAll(
+ convertEndpoints(new ArtifactResolutionServiceConverter(), protocols, artifactServices));
- /**
- * Get endpoint expression(s) for {@link SingleLogoutService} endpoint(s) using SAML 2.0 HTTP-Artifact binding.
- *
- * <p>Endpoints may omit scheme but must specify port and full path.</p>
- *
- * @return endpoint URLs
- */
- @Nonnull @Unmodifiable @NotLive public List<String> getLogoutArtifactEndpoints() {
- return logoutArtifact.stream()
- .map(this::getProcessedEndpoint)
- .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
- }
+ int index = 1;
+ for (final IndexedEndpoint e : role.getArtifactResolutionServices()) {
+ e.setIndex(index++);
+ }
+
+ protocols.forEach(role::addSupportedProtocol);
- /**
- * Get endpoint expression(s) for {@link SingleLogoutService} endpoint(s) using SAML 2.0 SOAP binding.
- *
- * <p>Endpoints may omit scheme but must specify port and full path.</p>
- *
- * @return endpoint URLs
- */
- @Nonnull @Unmodifiable @NotLive public List<String> getLogoutSoapEndpoints() {
- return logoutSoap.stream()
- .map(this::getProcessedEndpoint)
- .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
+ return role;
}
- /**
- * Get endpoint expression(s) for {@link AssertionConsumerService} endpoint(s) using SAML 2.0 HTTP-POST binding.
- *
- * <p>Endpoints may omit scheme but must specify port and full path.</p>
- *
- * @return endpoint URLs
- */
- @Nonnull @Unmodifiable @NotLive public List<String> getACSPostEndpoints() {
- return acsPost.stream()
- .map(this::getProcessedEndpoint)
- .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
- }
+ /** {@inheritDoc} */
+ @Nullable public AttributeAuthorityDescriptor getAttributeAuthorityDescriptor() {
+ if (!aa) {
+ return null;
+ }
- /**
- * Get endpoint expression(s) for {@link AssertionConsumerService} endpoint(s) using SAML 2.0 HTTP-Artifact binding.
- *
- * <p>Endpoints may omit scheme but must specify port and full path.</p>
- *
- * @return endpoint URLs
- */
- @Nonnull @Unmodifiable @NotLive public List<String> getACSArtifactEndpoints() {
- return acsArtifact.stream()
- .map(this::getProcessedEndpoint)
- .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
- }
+ final XMLObjectBuilderFactory bf = XMLObjectProviderRegistrySupport.getBuilderFactory();
+
+ final SAMLObjectBuilder<AttributeAuthorityDescriptor> builder =
+ (SAMLObjectBuilder<AttributeAuthorityDescriptor>) bf.<AttributeAuthorityDescriptor>ensureBuilder(
+ AttributeAuthorityDescriptor.DEFAULT_ELEMENT_NAME);
+ final AttributeAuthorityDescriptor role = builder.buildObject();
+
+ final List<String> protocols = new ArrayList<>();
- /**
- * Get endpoint expression(s) for {@link AssertionConsumerService} endpoint(s) using SAML 2.0 PAOS binding.
- *
- * <p>Endpoints may omit scheme but must specify port and full path.</p>
- *
- * @return endpoint URLs
- */
- @Nonnull @Unmodifiable @NotLive public List<String> getACSPaosEndpoints() {
- return acsPaos.stream()
- .map(this::getProcessedEndpoint)
- .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
+ role.getAttributeServices().addAll(
+ convertEndpoints(new AttributeServiceConverter(), protocols, attributeServices));
+
+ protocols.forEach(role::addSupportedProtocol);
+
+ return role;
}
-
+
/**
* Dual-use certificates.
*
* @return base64-encoded certificates
- *
- * @throws CertificateException if unable to decode
- * @throws EncodingException if unable to encode
*/
- @Nullable @NotLive public List<String> getCertificates() throws CertificateException, EncodingException {
- final List<String> encoded = new ArrayList<>();
-
- for (final String c : certificatePaths) {
- assert c != null;
- encoded.add(getEncodedCertificate(c));
- }
-
- return encoded;
+ @Nonnull @Unmodifiable @NotLive public List<String> getCertificates() {
+ return certificatePaths.stream()
+ .map(this::getEncodedCertificate)
+ .filter(Predicates.notNull())
+ .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
}
/**
* Signing-only certificate path(s).
*
* @return base64-encoded certificates
- *
- * @throws CertificateException if unable to decode
- * @throws EncodingException if unable to encode
*/
- @Nullable @NotLive public List<String> getSigningCertificates() throws CertificateException, EncodingException {
- final List<String> encoded = new ArrayList<>();
-
- for (final String c : signingPaths) {
- assert c != null;
- encoded.add(getEncodedCertificate(c));
- }
-
- return encoded;
+ @Nonnull @Unmodifiable @NotLive public List<String> getSigningCertificates() {
+ return signingPaths.stream()
+ .map(this::getEncodedCertificate)
+ .filter(Predicates.notNull())
+ .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
}
/**
* Encryption-only certificate path(s).
*
* @return base64-encoded certificates
- *
- * @throws CertificateException if unable to decode
- * @throws EncodingException if unable to encode
*/
- @Nullable @NotLive public List<String> getEncryptionCertificates() throws CertificateException, EncodingException {
- final List<String> encoded = new ArrayList<>();
-
- for (final String c : encryptionPaths) {
- assert c != null;
- encoded.add(getEncodedCertificate(c));
- }
-
- return encoded;
+ @Nonnull @Unmodifiable @NotLive public List<String> getEncryptionCertificates() {
+ return encryptionPaths.stream()
+ .map(this::getEncodedCertificate)
+ .filter(Predicates.notNull())
+ .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
}
/**
@@ -454,10 +290,15 @@ public class MetadataGenCommandLineArguments extends AbstractIdPHomeAwareCommand
*
* @return argument value
*/
- public boolean isOmitNamespaces() {
+ public boolean isOmitNamespaceDeclarations() {
return omitNamespaces;
}
+ /** {@inheritDoc} */
+ @Nullable public Set<Namespace> getAdditionalNamespaces() {
+ return CollectionSupport.singleton(new Namespace("urn:mace:shibboleth:metadata:oidc:1.0", "oidcmd"));
+ }
+
/**
* Output file path (stdout used otherwise).
*
@@ -467,27 +308,6 @@ public class MetadataGenCommandLineArguments extends AbstractIdPHomeAwareCommand
return outputFile;
}
- // Computed values.
-
- /**
- * Compute the appropriate protocol support string.
- *
- * @return the protocolSupportEnumeration constant
- */
- @Nonnull public String getProtocolSupportEnumeration() {
- final List<String> protocolSupportEnum = new ArrayList<>();
- if (isSAML2()) {
- protocolSupportEnum.add(SAMLConstants.SAML20P_NS);
- }
- if (isCAS()) {
- protocolSupportEnum.add(AbstractProtocolConfiguration.PROTOCOL_URI);
- }
- if (isOIDC()) {
- protocolSupportEnum.add("http://openid.net/specs/openid-connect-core-1_0.html");
- }
- return StringSupport.listToStringValue(protocolSupportEnum, " ");
- }
-
/** {@inheritDoc} */
@Override
@Nonnull public synchronized Logger getLog() {
@@ -501,10 +321,6 @@ public class MetadataGenCommandLineArguments extends AbstractIdPHomeAwareCommand
/** {@inheritDoc} */
@Override
public void validate() throws IllegalArgumentException {
- if (!saml2 && !cas && !oidc) {
- saml2 = true;
- }
-
if (!sp && !idp && !aa) {
sp = true;
}
@@ -514,32 +330,17 @@ public class MetadataGenCommandLineArguments extends AbstractIdPHomeAwareCommand
@Override
public void printHelp(@Nonnull final PrintStream out) {
super.printHelp(out);
- out.println(String.format(" %-20s %s", "--entityID, --id", "The entityID (or client_id, etc.)"));
-
- out.println(String.format(" %-20s %s", "--saml2", "Output SAML 2.0 metadata."));
- out.println(String.format(" %-20s %s", "--cas", "Output CAS metadata."));
- out.println(String.format(" %-20s %s", "--oidc", "Output OIDC metadata."));
+ out.println(String.format(" %-20s %s", "--entityID, --client_id, --id", "The entityID (or client_id, etc.)"));
out.println(String.format(" %-20s %s", "--sp", "Output SP role."));
- out.println(String.format(" %-20s %s", "--idp", "Ou tput IdP role."));
+ out.println(String.format(" %-20s %s", "--idp", "Output IdP role."));
out.println(String.format(" %-20s %s", "--aa", "Output Attribute Authority role."));
- out.println(String.format(" %-20s %s", "--sso-redirect", "Endpoint for SAML 2.0 SSO HTTP-Redirect endpoint"));
- out.println(String.format(" %-20s %s", "--sso-post", "Endpoint for SAML 2.0 SSO HTTP-POST endpoint"));
- out.println(String.format(" %-20s %s", "--sso-artifact", "Endpoint for SAML 2.0 SSO HTTP-Artifact endpoint"));
- out.println(String.format(" %-20s %s", "--sso-soap", "Endpoint for SAML 2.0 SSO SOAP endpoint"));
-
- out.println(String.format(" %-20s %s", "--artifact-soap, --artifact", "Endpoint for SAML 2.0 Artifact Resolution SOAP endpoint"));
- out.println(String.format(" %-20s %s", "--attr-soap", "Endpoint for SAML 2.0 Attribute Query SOAP endpoint"));
-
- out.println(String.format(" %-20s %s", "--logout-redirect", "Endpoint for SAML 2.0 SLO HTTP-Redirect endpoint"));
- out.println(String.format(" %-20s %s", "--logout-post", "Endpoint for SAML 2.0 SLO HTTP-POST endpoint"));
- out.println(String.format(" %-20s %s", "--logout-artifact", "Endpoint for SAML 2.0 SLO HTTP-Artifact endpoint"));
- out.println(String.format(" %-20s %s", "--logout-soap", "Endpoint for SAML 2.0 SLO SOAP endpoint"));
-
- out.println(String.format(" %-20s %s", "--acs, --acs-post, -h", "Endpoint for SAML 2.0 ACS HTTP-POST endpoint"));
- out.println(String.format(" %-20s %s", "--acs-artifact", "Endpoint for SAML 2.0 ACS HTTP-Artifact endpoint"));
- out.println(String.format(" %-20s %s", "--ecp, --acs-paos", "Endpoint for SAML 2.0 ACS ECP/PAOS endpoint"));
+ out.println(String.format(" %-20s %s", "--sso", "Binding/Endpoint for SingleSignOnService"));
+ out.println(String.format(" %-20s %s", "--logout, --slo", "Binding/Endpoint for SingleLogoutService"));
+ out.println(String.format(" %-20s %s", "--artifact", "Binding/Endpoint for ArtifactResolutionService"));
+ out.println(String.format(" %-20s %s", "--attribute-query, --query", "Binding/Endpoint for AttributeService"));
+ out.println(String.format(" %-20s %s", "--acs", "Binding/Endpoint for AssertionConsumerService"));
out.println(String.format(" %-20s %s", "--certificate, --cert, -c", "Path to dual-use certificate."));
out.println(String.format(" %-20s %s", "--signing, -x", "Path to signing certificate."));
@@ -556,34 +357,33 @@ public class MetadataGenCommandLineArguments extends AbstractIdPHomeAwareCommand
* @param path certificate file path
*
* @return encoded string
- *
- * @throws CertificateException if unable to decode
- * @throws EncodingException if unable to encode
*/
- @Nonnull private String getEncodedCertificate(@Nonnull final String path)
- throws CertificateException, EncodingException {
- final X509Certificate cert = X509Support.decodeCertificate(new File(path));
- return Base64Support.encode(cert.getEncoded(), true);
+ @Nullable private String getEncodedCertificate(@Nonnull final String path) {
+ try {
+ final X509Certificate cert = X509Support.decodeCertificate(new File(path));
+ return Base64Support.encode(cert.getEncoded(), true);
+ } catch (final CertificateException | EncodingException e) {
+ getLog().warn("Unable to decode and re-encode certificate at path {}", path, e);
+ return null;
+ }
}
-
+
/**
- * Process an endpoint expression into an absolute URL.
- *
- * <p>For now, this merely detects the http schemes and if absent, adds the https scheme.</p>
+ * Convert the expressions into endpoints.
*
- * @param endpoint input expression
+ * @param <T> endpoint type
+ * @param converter endpoint converter
+ * @param protocols accumulator for protocol support values
+ * @param input raw argument list
*
- * @return an absolute URL or null if input was null
+ * @return converted endpoints
*/
- @Nullable private String getProcessedEndpoint(@Nullable final String endpoint) {
- if (endpoint == null) {
- return null;
- }
-
- if (endpoint.startsWith("https://") || endpoint.startsWith("http://")) {
- return endpoint;
- }
- return "https://" + endpoint;
+ @Nonnull private <T extends Endpoint> Collection<T> convertEndpoints(
+ @Nonnull final BiFunction<String,List<String>,T> converter, @Nonnull @Live final List<String> protocols,
+ @Nonnull final Collection<String> input) {
+ return input.stream()
+ .map(s -> converter.apply(s, protocols))
+ .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
}
}
\ No newline at end of file
diff --git a/metadatagen-impl/src/main/java/net/shibboleth/idp/plugin/metadatagen/impl/SingleLogoutServiceConverter.java b/metadatagen-impl/src/main/java/net/shibboleth/idp/plugin/metadatagen/impl/SingleLogoutServiceConverter.java
new file mode 100644
index 0000000..b756974
--- /dev/null
+++ b/metadatagen-impl/src/main/java/net/shibboleth/idp/plugin/metadatagen/impl/SingleLogoutServiceConverter.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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.
+ */
+
+package net.shibboleth.idp.plugin.metadatagen.impl;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.saml.saml2.metadata.SingleLogoutService;
+
+import net.shibboleth.idp.cas.config.AbstractProtocolConfiguration;
+import net.shibboleth.shared.annotation.constraint.Live;
+import net.shibboleth.shared.collection.Pair;
+
+/**
+ * JCommander support for parsing a binding/endpoint pair into a {@link SingleLogoutService}.
+ */
+public class SingleLogoutServiceConverter extends org.opensaml.saml.metadata.generator.impl.SingleLogoutServiceConverter {
+
+ /** {@inheritDoc} */
+ @Nonnull public SingleLogoutService apply(@Nullable final String value,
+ @Nullable @Live final List<String> protocols) {
+ return getProcessedEndpoint(protocols, value);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull protected Pair<String,String> getProtocolAndBinding(@Nonnull final String input) {
+ if (input.startsWith("CAS/")) {
+ return new Pair<>(AbstractProtocolConfiguration.PROTOCOL_URI,
+ AbstractProtocolConfiguration.PROTOCOL_URI + "/logout");
+ }
+ return super.getProtocolAndBinding(input);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull protected String getLocation(@Nonnull final String input) {
+ if (input.startsWith("CAS/")) {
+ return "urn:mace:shibboleth:profile:CAS:logout";
+ }
+ return super.getLocation(input);
+ }
+
+}
\ No newline at end of file
diff --git a/metadatagen-impl/src/main/resources/metadatagen-templates/AttributeAuthorityDescriptor.vm b/metadatagen-impl/src/main/resources/metadatagen-templates/AttributeAuthorityDescriptor.vm
deleted file mode 100644
index 2a2d21b..0000000
--- a/metadatagen-impl/src/main/resources/metadatagen-templates/AttributeAuthorityDescriptor.vm
+++ /dev/null
@@ -1,3 +0,0 @@
- <md:AttributeAuthorityDescriptor protocolSupportEnumeration="$args.protocolSupportEnumeration">
-#parse("/metadatagen-templates/KeyDescriptors.vm")
- </md:AttributeAuthorityDescriptor>
diff --git a/metadatagen-impl/src/main/resources/metadatagen-templates/EntityDescriptor.vm b/metadatagen-impl/src/main/resources/metadatagen-templates/EntityDescriptor.vm
deleted file mode 100644
index 49239da..0000000
--- a/metadatagen-impl/src/main/resources/metadatagen-templates/EntityDescriptor.vm
+++ /dev/null
@@ -1,13 +0,0 @@
-<md:EntityDescriptor#if (!$args.omitNamespaces)#foreach ($ns in $namespaces.entrySet()) xmlns:$ns.key="$ns.value"#end#end entityID="$args.entityID">
-
-#if ($args.IDP)
-#parse("/metadatagen-templates/IDPSSODescriptor.vm")
-#end
-#if ($args.AA)
-#parse("/metadatagen-templates/AttributeAuthorityDescriptor.vm")
-#end
-#if ($args.SP)
-#parse("/metadatagen-templates/SPSSODescriptor.vm")
-#end
-
-</md:EntityDescriptor>
diff --git a/metadatagen-impl/src/main/resources/metadatagen-templates/IDPSSODescriptor.vm b/metadatagen-impl/src/main/resources/metadatagen-templates/IDPSSODescriptor.vm
deleted file mode 100644
index b972947..0000000
--- a/metadatagen-impl/src/main/resources/metadatagen-templates/IDPSSODescriptor.vm
+++ /dev/null
@@ -1,4 +0,0 @@
- <md:IDPSSODescriptor protocolSupportEnumeration="$args.protocolSupportEnumeration">
-#parse("/metadatagen-templates/KeyDescriptors.vm")
-#parse("/metadatagen-templates/SingleLogoutServices.vm")
- </md:IDPSSODescriptor>
diff --git a/metadatagen-impl/src/main/resources/metadatagen-templates/KeyDescriptors.vm b/metadatagen-impl/src/main/resources/metadatagen-templates/KeyDescriptors.vm
deleted file mode 100644
index 0907e7d..0000000
--- a/metadatagen-impl/src/main/resources/metadatagen-templates/KeyDescriptors.vm
+++ /dev/null
@@ -1,30 +0,0 @@
-#foreach ($cert in $args.certificates) <md:KeyDescriptor>
- <ds:KeyInfo>
- <ds:X509Data>
- <ds:X509Certificate>
-$cert
- </ds:X509Certificate>
- </ds:X509Data>
- </ds:KeyInfo>
- </md:KeyDescriptor>
-#end
-#foreach ($cert in $args.signingCertificates) <md:KeyDescriptor use="signing">
- <ds:KeyInfo>
- <ds:X509Data>
- <ds:X509Certificate>
-$cert
- </ds:X509Certificate>
- </ds:X509Data>
- </ds:KeyInfo>
- </md:KeyDescriptor>
-#end
-#foreach ($cert in $args.encryptionCertificates) <md:KeyDescriptor use="encryption">
- <ds:KeyInfo>
- <ds:X509Data>
- <ds:X509Certificate>
-$cert
- </ds:X509Certificate>
- </ds:X509Data>
- </ds:KeyInfo>
- </md:KeyDescriptor>
-#end
diff --git a/metadatagen-impl/src/main/resources/metadatagen-templates/SPSSODescriptor.vm b/metadatagen-impl/src/main/resources/metadatagen-templates/SPSSODescriptor.vm
deleted file mode 100644
index 4e5c076..0000000
--- a/metadatagen-impl/src/main/resources/metadatagen-templates/SPSSODescriptor.vm
+++ /dev/null
@@ -1,18 +0,0 @@
- <md:SPSSODescriptor protocolSupportEnumeration="$args.protocolSupportEnumeration">
-#parse("/metadatagen-templates/KeyDescriptors.vm")
-#foreach ($loc in $args.artifactSoapEndpoints)
- <md:ArtifactResolutionService index="$foreach.count" Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="$loc" />
-#end
-#parse("/metadatagen-templates/SingleLogoutServices.vm")
-#set ($index = 0)
-#foreach ($loc in $args.ACSPostEndpoints)#set ( $index = $index + 1 )
- <md:AssertionConsumerService index="$index" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="$loc" />
-#end
-#set ($index = $args.ACSPostEndpoints.size())
-#foreach ($loc in $args.ACSArtifactEndpoints)#set ( $index = $index + 1 )
- <md:AssertionConsumerService index="$index" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="$loc" />
-#end
-#foreach ($loc in $args.ACSPaosEndpoints)#set ( $index = $index + 1 )
- <md:AssertionConsumerService index="$index" Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Location="$loc" />
-#end
- </md:SPSSODescriptor>
diff --git a/metadatagen-impl/src/main/resources/metadatagen-templates/SingleLogoutServices.vm b/metadatagen-impl/src/main/resources/metadatagen-templates/SingleLogoutServices.vm
deleted file mode 100644
index ef854c3..0000000
--- a/metadatagen-impl/src/main/resources/metadatagen-templates/SingleLogoutServices.vm
+++ /dev/null
@@ -1,12 +0,0 @@
-#foreach ($loc in $args.logoutRedirectEndpoints)
- <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="$loc" />
-#end
-#foreach ($loc in $args.logoutPostEndpoints)
- <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="$loc" />
-#end
-#foreach ($loc in $args.logoutArtifactEndpoints)
- <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="$loc" />
-#end
-#foreach ($loc in $args.logoutSoapEndpoints)
- <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="$loc" />
-#end
diff --git a/metadatagen-impl/src/main/resources/net/shibboleth/idp/plugin/metadatagen/conf/velocity.xml b/metadatagen-impl/src/main/resources/net/shibboleth/idp/plugin/metadatagen/conf/velocity.xml
index 449d116..b4471ec 100644
--- a/metadatagen-impl/src/main/resources/net/shibboleth/idp/plugin/metadatagen/conf/velocity.xml
+++ b/metadatagen-impl/src/main/resources/net/shibboleth/idp/plugin/metadatagen/conf/velocity.xml
@@ -37,6 +37,8 @@
<bean id="shibboleth.IdentifiableBeanPostProcessor"
class="net.shibboleth.shared.spring.config.IdentifiableBeanPostProcessor" />
+ <bean id="shibboleth.OpenSAMLConfig" class="net.shibboleth.profile.spring.impl.OpenSAMLConfigBean" />
+
<util:map id="shibboleth.DefaultVelocityEngineProperties">
<entry key="parser.space_gobbling" value="%{idp.velocity.space.gobbling:bc}" />
<entry key="resource.loaders" value="file, classpath" />
@@ -48,6 +50,7 @@
</util:map>
<bean id="shibboleth.VelocityEngine" class="net.shibboleth.shared.spring.velocity.VelocityEngineFactoryBean"
+ depends-on="shibboleth.OpenSAMLConfig"
p:velocityPropertiesMap="#{getObject('shibboleth.VelocityEngineProperties') ?: getObject('shibboleth.DefaultVelocityEngineProperties')}" />
</beans>
diff --git a/metadatagen-impl/src/test/java/net/shibboleth/idp/plugin/metadatagen/impl/MetadataGenTest.java b/metadatagen-impl/src/test/java/net/shibboleth/idp/plugin/metadatagen/impl/MetadataGenTest.java
index 63e6542..a623f2e 100644
--- a/metadatagen-impl/src/test/java/net/shibboleth/idp/plugin/metadatagen/impl/MetadataGenTest.java
+++ b/metadatagen-impl/src/test/java/net/shibboleth/idp/plugin/metadatagen/impl/MetadataGenTest.java
@@ -19,15 +19,6 @@ package net.shibboleth.idp.plugin.metadatagen.impl;
import static org.testng.Assert.assertEquals;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.file.Files;
-
-import org.springframework.core.io.ClassPathResource;
import org.testng.annotations.Test;
import net.shibboleth.shared.cli.AbstractCommandLine;
@@ -41,74 +32,28 @@ public class MetadataGenTest {
// src/test/resources/net/shibboleth/idp/plugin/metadatagen/impl/extra2
private final static String IDP_HOME = "/Users/scantor/Documents/shibboleth5/java-identity-provider/idp-conf-impl/src/main/resources/net/shibboleth/idp/module";
private final boolean enabled = false;
-
- @Test(enabled = enabled) public void test() throws IOException {
- assertEquals(MetadataGenCLI.runMain(
- new String[] {
- "--home", IDP_HOME,
- "--verbose",
- "--DNSName", "my.idp.example.org",
- "+saml1",
- "--backChannel", IDP_HOME + "/credentials/idp-backchannel.crt",
- "+attributeFetch","+artifact", "+logout",
- }),
- AbstractCommandLine.RC_OK);
- }
-
- @Test(enabled = enabled) public void testProps() throws IOException {
- final File file1 = Files.createTempFile(getClass().getName(), ".props").toFile();
- file1.deleteOnExit();
- final ClassPathResource res1 = new ClassPathResource("/net/shibboleth/idp/plugin/metadatagen/impl/extra1");
- try (final InputStream stream = res1.getInputStream(); final OutputStream out = new BufferedOutputStream(new FileOutputStream(file1))) {
- stream.transferTo(out);
- }
- final File file2 = Files.createTempFile(getClass().getName(), ".props").toFile();
- file2.deleteOnExit();
- final ClassPathResource res2 = new ClassPathResource("/net/shibboleth/idp/plugin/metadatagen/impl/extra2");
- try (final InputStream stream = res2.getInputStream(); final OutputStream out = new BufferedOutputStream(new FileOutputStream(file2))) {
- stream.transferTo(out);
- }
-
- assertEquals(MetadataGenCLI.runMain(
- new String[] {
- "--home", IDP_HOME,
- "--verbose",
- "+saml1",
- "--propertyFiles", file1.getPath() +","+ file2.getPath(),
- "+attributeFetch","+artifact", "+logout",
- }),
- AbstractCommandLine.RC_OK);
- }
-
- @Test(enabled = enabled) public void noBc() throws IOException {
- assertEquals(MetadataGenCLI.runMain(
- new String[] {
- "--home", IDP_HOME,
- "--verbose", "+logout",
- "+saml1"}),
- AbstractCommandLine.RC_OK);
- }
-
- @Test(enabled = enabled) public void help() throws IOException {
- assertEquals(MetadataGenCLI.runMain(
- new String[] {
- "--home", IDP_HOME,
- "--help"}),
- AbstractCommandLine.RC_OK);
- }
- @Test(enabled = true) public void testSimple() {
+ @Test(enabled = enabled) public void testSimple() {
assertEquals(MetadataGenCLI.runMain(
new String[] {
"--home", IDP_HOME,
"--sp",
+ "--idp",
+ "--aa",
"--entityID", "https://sp.example.org",
"--cert", "/Users/scantor/Desktop/webauth2.crt",
- "--logout-redirect", "sp.example.org/Shibboleth.sso/SLO/Redirect",
- "--logout-redirect", "sp2.example.org/Shibboleth.ssoSLO/Redirect",
- "-h", "sp.example.org/Shibboleth.sso/SAML2/POST",
- "-h", "sp2.example.org/Shibboleth.sso/SAML2/POST",
- "--acs-paos", "sp.example.org/Shibboleth.sso/SAML2/ECP",
+ "--sso", "Redirect1/idp.example.org/idp/profile/SAML/SSO/Redirect",
+ "--sso", "Redirect/idp.example.org/idp/profile/SAML2/SSO/Redirect",
+ "--sso", "POST/idp.example.org/idp/profile/SAML2/SSO/POST",
+ "--sso", "SOAP/idp.example.org/idp/profile/SAML2/SSO/SOAP",
+ "--query", "SOAP/idp.example.org:8443/idp/profile/SAML2/AttributeQuery/SOAP",
+ "--query", "SOAP1/idp.example.org:8443/idp/profile/SAML/AttributeQuery/SOAP",
+ "--logout", "Redirect/sp.example.org/Shibboleth.sso/SLO/Redirect",
+ "--logout", "Artifact/sp.example.org/Shibboleth.sso/SLO/Artifact",
+ "--acs", "POST1/sp.example.org/Shibboleth.sso/SAML/POST",
+ "--acs", "POST/sp.example.org/Shibboleth.sso/SAML2/POST",
+ "--acs", "POST/sp2.example.org/Shibboleth.sso/SAML2/POST",
+ "--acs", "PAOS/sp.example.org/Shibboleth.sso/SAML2/ECP",
}),
AbstractCommandLine.RC_OK);
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list