Skip to content

Commit

Permalink
Merge pull request #46 from swedenconnect/feature/IS-45-skip-hostname…
Browse files Browse the repository at this point in the history
…-verification

IS-45 It is now possible to skip hostname verification
  • Loading branch information
martin-lindstrom authored Nov 13, 2023
2 parents fb98062 + 0de52cb commit 4356026
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,38 +24,44 @@

/**
* Configuration properties for metadata provider configuration.
*
*
* @author Martin Lindström
*/
@Data
public class MetadataProviderConfigurationProperties {

/**
* The location of the metadata. Can be an URL, a file, or even a classpath resource.
*/
private Resource location;


/**
* If the {@code location} is an HTTPS resource, this setting tells whether to skip hostname verification in the TLS
* connection (useful during testing).
*/
private Boolean skipHostnameVerification;

/**
* If the {@code location} setting is an URL, a "backup location" may be assigned to store downloaded metadata.
*/
private File backupLocation;

/**
* If the {@code location} setting is an URL, setting the MDQ-flag means that the metadata MDQ
* (https://www.ietf.org/id/draft-young-md-query-17.html) protocol is used.
*/
private Boolean mdq;

/**
* The certificate used to validate the metadata.
*/
private X509Certificate validationCertificate;

/**
* If the {@code location} setting is an URL and a HTTP proxy is required this setting configures this proxy.
*/
private HttpProxy httpProxy;

/**
* Configuration properties for an HTTP proxy.
*/
Expand All @@ -81,6 +87,6 @@ public static class HttpProxy {
* The proxy user name (optional).
*/
private String userName;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ MetadataResolver metadataResolver() {
for (final MetadataProviderConfigurationProperties p : this.properties.getMetadataProviders()) {
settings[pos++] = MetadataProviderSettings.builder()
.location(p.getLocation())
.skipHostnameVerification(p.getSkipHostnameVerification())
.backupLocation(p.getBackupLocation())
.mdq(p.getMdq())
.validationCertificate(p.getValidationCertificate())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

/**
* Settings for configuring SAML metadata providers (resolvers).
*
*
* @author Martin Lindström
*/
public class MetadataProviderSettings extends AbstractSettings {
Expand All @@ -50,13 +50,28 @@ protected MetadataProviderSettings(final Map<String, Object> settings) {

/**
* Gets the location of the metadata. Can be an URL, a file, or even a classpath resource.
*
*
* @return the metadata location
*/
public Resource getLocation() {
return this.getSetting(SAML_METADATA_PROVIDER_LOCATION);
}

/**
* If the {@code location} is an HTTPS resource, this setting tells whether to skip hostname verification in the TLS
* connection (useful during testing).
*/
public static final String SAML_METADATA_PROVIDER_SKIP_HOSTNAME_VERIFICATION = "skip-hostname-verification";

/**
* Tells whether to skip hostname verification in the TLS connection (useful during testing).
*
* @return {@code true} if hostname verification should be skipped
*/
public Boolean getSkipHostnameVerification() {
return this.getSetting(SAML_METADATA_PROVIDER_SKIP_HOSTNAME_VERIFICATION);
}

/**
* If the {@code location} setting is an URL, a "backup location" may be assigned to store downloaded metadata. A
* {@link File}.
Expand All @@ -66,7 +81,7 @@ public Resource getLocation() {
/**
* If the {@code location} setting is an URL, a "backup location" may be assigned to store downloaded metadata. This
* method returns this file.
*
*
* @return a file or {@code null}
*/
public File getBackupLocation() {
Expand All @@ -82,7 +97,7 @@ public File getBackupLocation() {
/**
* If the {@code location} setting is an URL, setting the MDQ-flag means that the metadata MDQ
* (https://www.ietf.org/id/draft-young-md-query-17.html) protocol is used. This method returns this setting.
*
*
* @return whether MDQ is active or not
*/
public Boolean getMdq() {
Expand All @@ -96,7 +111,7 @@ public Boolean getMdq() {

/**
* Gets the certificate used to validate the metadata.
*
*
* @return the validation certificate or {@code null} if not assigned
*/
public X509Certificate getValidationCertificate() {
Expand All @@ -111,7 +126,7 @@ public X509Certificate getValidationCertificate() {

/**
* Gets the HTTP proxy settings.
*
*
* @return the proxy settings or {@code null}
*/
public HttpProxySettings getHttpProxy() {
Expand Down Expand Up @@ -148,20 +163,30 @@ private Builder() {

/**
* Assigns the location of the metadata. Can be an URL, a file, or even a classpath resource.
*
*
* @param location the metadata location
* @return the builder
*/
public Builder location(final Resource location) {
return this.setting(SAML_METADATA_PROVIDER_LOCATION, location);
}

/**
* Tells whether to skip hostname verification in the TLS connection (useful during testing).
*
* @param {@code true} if hostname verification should be skipped
* @return the builder
*/
public Builder skipHostnameVerification(final Boolean skip) {
return this.setting(SAML_METADATA_PROVIDER_SKIP_HOSTNAME_VERIFICATION, skip);
}

/**
* Assigns the backup file.
* <p>
* If the {@code location} setting is an URL, a "backup location" may be assigned to store downloaded metadata.
* </p>
*
*
* @param backupLocation the backup location file
* @return the builder
*/
Expand All @@ -175,7 +200,7 @@ public Builder backupLocation(final File backupLocation) {
* If the {@code location} setting is an URL, setting the MDQ-flag means that the metadata MDQ
* (https://www.ietf.org/id/draft-young-md-query-17.html) protocol is used.
* </p>
*
*
* @param mdq whether MDQ should be be used
* @return the builder
*/
Expand All @@ -185,7 +210,7 @@ public Builder mdq(final Boolean mdq) {

/**
* Assigns the certificate used to validate the metadata.
*
*
* @param validationCertificate the validation certificate
* @return the builder
*/
Expand All @@ -195,7 +220,7 @@ public Builder validationCertificate(final X509Certificate validationCertificate

/**
* Assigns the HTTP proxy settings.
*
*
* @param httpProxy the proxy settings
* @return the builder
*/
Expand All @@ -206,10 +231,12 @@ public Builder httpProxy(final HttpProxySettings httpProxy) {
/** {@inheritDoc} */
@Override
protected void applyDefaultSettings() {
if (this.getSettings().get(SAML_METADATA_PROVIDER_SKIP_HOSTNAME_VERIFICATION) == null) {
this.skipHostnameVerification(Boolean.FALSE);
}
if (this.getSettings().get(SAML_METADATA_PROVIDER_MDQ) == null) {
this.mdq(false);
}
// TODO: Default to Sweden Connect prod?
}

/** {@inheritDoc} */
Expand All @@ -222,7 +249,7 @@ protected MetadataProviderSettings buildObject() {

/**
* Settings for representing HTTP proxy configuration.
*
*
* @author Martin Lindström
*/
public static class HttpProxySettings extends AbstractSettings {
Expand All @@ -245,7 +272,7 @@ protected HttpProxySettings(final Map<String, Object> settings) {

/**
* Gets the HTTP proxy host.
*
*
* @return the HTTP proxy host
*/
public String getHost() {
Expand All @@ -259,7 +286,7 @@ public String getHost() {

/**
* Gets the HTTP proxy port.
*
*
* @return the HTTP proxy port
*/
public Integer getPort() {
Expand All @@ -273,7 +300,7 @@ public Integer getPort() {

/**
* Gets the HTTP proxy user name.
*
*
* @return the proxy user name or {@code null}
*/
public String getUserName() {
Expand All @@ -287,7 +314,7 @@ public String getUserName() {

/**
* Gets the HTTP proxy password.
*
*
* @return the HTTP proxy password or {@code null}
*/
public String getPassword() {
Expand Down Expand Up @@ -324,7 +351,7 @@ private Builder() {

/**
* Assigns the HTTP proxy host.
*
*
* @param host the HTTP proxy host
* @return the builder
*/
Expand All @@ -334,7 +361,7 @@ public Builder host(final String host) {

/**
* Assigns the HTTP proxy port.
*
*
* @param port the HTTP proxy port
* @return the builder
*/
Expand All @@ -344,23 +371,23 @@ public Builder port(final Integer port) {

/**
* Assigns the HTTP proxy user name.
*
*
* @param userName the proxy user name
* @return the builder
*/
public Builder userName(final String userName) {
return this.setting(HTTP_PROXY_USER_NAME, userName);
}

/**
* Assigns the HTTP proxy password.
*
*
* @param password the HTTP proxy password
* @return the builder
*/
public Builder password(final String password) {
return this.setting(HTTP_PROXY_PASSWORD, password);
}
}

/** {@inheritDoc} */
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.TrustManager;

import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.ssl.DefaultHostnameVerifier;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.saml.metadata.resolver.MetadataResolver;
import org.springframework.core.io.FileSystemResource;
Expand Down Expand Up @@ -129,7 +131,9 @@ else if (FileSystemResource.class.isInstance(md.getLocation())) {
private static HttpClient createHttpClient(final MetadataProviderSettings config) {
try {
final List<TrustManager> managers = Arrays.asList(HttpClientSupport.buildNoTrustX509TrustManager());
final HostnameVerifier hnv = new DefaultHostnameVerifier();
final HostnameVerifier hnv = Optional.ofNullable(config.getSkipHostnameVerification()).orElse(false)
? new NoopHostnameVerifier()
: new DefaultHostnameVerifier();

HttpClientBuilder builder = new HttpClientBuilder();
builder.setUseSystemProperties(true);
Expand Down

0 comments on commit 4356026

Please sign in to comment.