Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ versions.springBootVersion = "3.5.13"
versions.guavaVersion = "33.5.0-jre"
versions.seleniumVersion = "4.43.0"
versions.braveVersion = "6.3.1"
versions.opensaml = "4.0.1"
versions.opensaml = "4.3.2"

// Versions we're overriding from the Spring Boot Bom (Dependabot does not issue PRs to bump these versions, so we need to manually bump them)
ext["selenium.version"] = "${versions.seleniumVersion}" // Selenium for integration tests only
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.saml2.Saml2Exception;
import org.springframework.security.saml2.core.OpenSamlInitializationService;
import org.springframework.security.saml2.core.Saml2Error;
import org.springframework.security.saml2.core.Saml2ErrorCodes;
import org.springframework.security.saml2.core.Saml2ResponseValidatorResult;
Expand Down Expand Up @@ -113,7 +112,7 @@
public final class OpenSaml4AuthenticationProvider implements AuthenticationProvider, ZoneAware {

static {
OpenSamlInitializationService.initialize();
SamlConfiguration.setupOpenSaml();
}

private final Log logger = LogFactory.getLog(this.getClass());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.saml2.Saml2Exception;
import org.springframework.security.saml2.core.OpenSamlInitializationService;
import org.springframework.security.saml2.core.Saml2Error;
import org.springframework.security.saml2.core.Saml2ErrorCodes;
import org.springframework.security.saml2.core.Saml2ResponseValidatorResult;
Expand Down Expand Up @@ -73,7 +72,7 @@
public final class Saml2BearerGrantAuthenticationConverter implements AuthenticationConverter {

static {
OpenSamlInitializationService.initialize();
SamlConfiguration.setupOpenSaml();
}

private static final AssertionUnmarshaller assertionUnmarshaller;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,31 @@
import org.cloudfoundry.identity.uaa.util.TimeService;
import org.cloudfoundry.identity.uaa.util.TimeServiceImpl;
import org.cloudfoundry.identity.uaa.util.UaaHttpRequestUtils;
import org.opensaml.core.config.ConfigurationService;
import org.opensaml.core.config.InitializationException;
import org.opensaml.core.config.Initializer;
import org.opensaml.security.config.GlobalNamedCurveRegistryInitializer;
import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.security.saml2.Saml2Exception;
import org.springframework.security.saml2.core.OpenSamlInitializationService;
import org.springframework.web.client.RestTemplate;

import java.util.Properties;
import java.util.ServiceLoader;
import java.util.concurrent.atomic.AtomicBoolean;

import static org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap.CONFIG_PROPERTY_ECDH_DEFAULT_KDF;

@Slf4j
@EnableConfigurationProperties({SamlConfigProps.class})
@DependsOn({"setUpBouncyCastle", "setupOpenSaml"})
@Configuration
@Data
public class SamlConfiguration {
Expand Down Expand Up @@ -54,6 +69,31 @@ public class SamlConfiguration {
@Value("${login.saml.socket.soTimeout:10000}")
private int socketReadTimeout = 10_000;

private static final AtomicBoolean samlInitialized = new AtomicBoolean(false);

@Bean
public static Boolean setupOpenSaml() {
if (samlInitialized.compareAndSet(false, true)) {
Properties props = ConfigurationService.getConfigurationProperties();
props.put(CONFIG_PROPERTY_ECDH_DEFAULT_KDF, DefaultSecurityConfigurationBootstrap.PBKDF2);
Class<?> toSkip = GlobalNamedCurveRegistryInitializer.class;
ServiceLoader.load(Initializer.class).stream().filter((provider) -> provider.type() != toSkip).forEach((provider) -> init(provider));
try {
OpenSamlInitializationService.initialize();
} catch (NoClassDefFoundError | NoSuchMethodError e) {
// ignore
}
}
return Boolean.TRUE;
}

private static void init(ServiceLoader.Provider<Initializer> provider) {
try {
provider.get().init();
} catch (InitializationException ex) {
throw new Saml2Exception(ex);
}
}
@Bean
public String samlEntityID() {
return samlEntityID;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static org.cloudfoundry.identity.uaa.provider.saml.SamlMetadataEndpoint.DEFAULT_REGISTRATION_ID;

@DependsOn({"setUpBouncyCastle", "setupOpenSaml"})
@Configuration
@Slf4j
public class SamlRelyingPartyRegistrationRepositoryConfig {
Expand All @@ -44,7 +44,6 @@ public SamlRelyingPartyRegistrationRepositoryConfig(@Qualifier("samlEntityID") S
this.signatureAlgorithms = signatureAlgorithms;
}

@DependsOn({"setUpBouncyCastle"})
@Bean
RelyingPartyRegistrationRepository relyingPartyRegistrationRepository(SamlIdentityProviderConfigurator samlIdentityProviderConfigurator) {
SamlKeyManagerFactory.SamlConfigPropsSamlKeyManagerImpl samlKeyManager = new SamlKeyManagerFactory.SamlConfigPropsSamlKeyManagerImpl(samlConfigProps);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ public class BootstrapSamlIdentityProviderDataTests {

@BeforeEach
void beforeEach() {
SamlConfiguration.setupOpenSaml();
bootstrap = new BootstrapSamlIdentityProviderData(new SamlIdentityProviderConfigurator(mock(JdbcIdentityProviderProvisioning.class), new IdentityZoneManagerImpl(), mock(FixedHttpMetaDataProvider.class)));
singleAdd = new SamlIdentityProviderDefinition()
.setMetaDataLocation(BootstrapSamlIdentityProviderDataTests.XML_WITHOUT_ID.formatted(new RandomValueStringGenerator().generate()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
import org.junit.jupiter.params.provider.NullSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.opensaml.core.config.InitializationException;
import org.opensaml.core.config.InitializationService;
import org.opensaml.saml.saml2.core.AuthnContext;
import org.opensaml.saml.saml2.core.Response;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -183,7 +182,7 @@ void configureProvider() throws SecurityException, SQLException, InitializationE
RequestContextHolder.setRequestAttributes(servletWebRequest);
DbUtils dbUtils = new DbUtils();

InitializationService.initialize();
SamlConfiguration.setupOpenSaml();

ScimGroupProvisioning groupProvisioning = new JdbcScimGroupProvisioning(
namedJdbcTemplate, new JdbcPagingListFactory(namedJdbcTemplate, limitSqlAdapter),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.cloudfoundry.identity.uaa.zone.IdentityZone;
import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
Expand Down Expand Up @@ -93,6 +94,11 @@ class OpenSaml4AuthenticationProviderUnitTests {

private final OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();

@BeforeEach
void setUp() {
SamlConfiguration.setupOpenSaml();
}

@AfterEach void cleanup() {
IdentityZoneHolder.clear();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@
import org.opensaml.saml.saml2.core.AttributeValue;
import org.w3c.dom.Element;

import org.springframework.security.saml2.core.OpenSamlInitializationService;

/**
* This was copied from Spring Security Test Classes
* <p/>
Expand All @@ -51,7 +49,7 @@
public final class TestCustomOpenSamlObjects {

static {
OpenSamlInitializationService.initialize();
SamlConfiguration.setupOpenSaml();
XMLObjectProviderRegistrySupport.getMarshallerFactory()
.registerMarshaller(CustomOpenSamlObject.TYPE_NAME,
new TestCustomOpenSamlObjects.CustomSamlObjectMarshaller());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@
import org.opensaml.xmlsec.signature.support.SignatureException;
import org.opensaml.xmlsec.signature.support.SignatureSupport;
import org.springframework.security.saml2.Saml2Exception;
import org.springframework.security.saml2.core.OpenSamlInitializationService;
import org.springframework.security.saml2.core.Saml2X509Credential;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;

Expand Down Expand Up @@ -101,7 +100,7 @@ public final class TestOpenSamlObjects {
public static final String RELYING_PARTY_ENTITY_ID = "https://localhost/saml2/service-provider-metadata/idp-alias";

static {
OpenSamlInitializationService.initialize();
SamlConfiguration.setupOpenSaml();
}

private TestOpenSamlObjects() {
Expand Down Expand Up @@ -133,6 +132,7 @@ static Response signedResponseWithOneAssertion() {

static Response signedResponseWithOneAssertion(Consumer<Response> responseConsumer) {
Response response = response();
response.setIssueInstant(Instant.now());
response.getAssertions().add(assertion());
responseConsumer.accept(response);
return signed(response, TestSaml2X509Credentials.assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID);
Expand All @@ -156,6 +156,7 @@ public static Assertion assertion(String username, String issuerEntityId, String
Assertion assertion = build(Assertion.DEFAULT_ELEMENT_NAME);
assertion.setID("A" + UUID.randomUUID());
assertion.setVersion(SAMLVersion.VERSION_20);
assertion.setIssueInstant(Instant.now());
assertion.setIssuer(issuer(issuerEntityId));
assertion.setSubject(subject(username));
assertion.setConditions(conditions());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.cloudfoundry.identity.uaa.db.beans.JdbcUrlCustomizer;
import org.cloudfoundry.identity.uaa.extensions.PollutionPreventionExtension;
import org.cloudfoundry.identity.uaa.impl.config.YamlServletProfileInitializer;
import org.cloudfoundry.identity.uaa.provider.saml.SamlConfiguration;
import org.cloudfoundry.identity.uaa.test.TestClient;
import org.cloudfoundry.identity.uaa.zone.ZoneContextPathSessionFilter;
import org.cloudfoundry.identity.uaa.zone.ZonePathContextRewritingFilter;
Expand Down Expand Up @@ -71,6 +72,7 @@ class TestPropertyInitializer implements ApplicationContextInitializer<Configura
@Override
public void initialize(ConfigurableWebApplicationContext applicationContext) {
System.setProperty("UAA_CONFIG_URL","classpath:integration_test_properties.yml");
SamlConfiguration.setupOpenSaml();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.cloudfoundry.identity.uaa.impl.config.YamlConfigurationValidator;
import org.cloudfoundry.identity.uaa.impl.config.YamlServletProfileInitializer;
import org.cloudfoundry.identity.uaa.provider.saml.SamlConfiguration;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeansException;
Expand Down Expand Up @@ -48,6 +49,7 @@ void invalidConfiguration() {
}

private static TestApplicationContext createApplicationContext() {
SamlConfiguration.setupOpenSaml();
var applicationContext = new TestApplicationContext();
var servletContext = new TestMockContext();
applicationContext.setServletContext(servletContext);
Expand Down
Loading