Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New SAML 2024.05.30 - Not to merge but just for SAML feature branch testing #2908

Draft
wants to merge 76 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
dd91275
remove: SAML extension library dependency
swalchemist Jan 24, 2024
316af55
Ignore non-functioning SAML tests
swalchemist Feb 13, 2024
65ac33b
update @Ignore - test now compiles
swalchemist Feb 23, 2024
38b3d94
feat: switch to new Spring Security SAML library
swalchemist Feb 27, 2024
2d6d669
feat: Supply metadata through /saml/metadata
Tallicia Mar 13, 2024
1cefd02
fix: handle case when Servlet Path is null and ensures test WithHttp…
Tallicia Mar 13, 2024
2deef93
remove: SAML extension library dependency
swalchemist Jan 24, 2024
843b0ce
Ignore non-functioning SAML tests
swalchemist Feb 13, 2024
9416e40
feat: Supply metadata through /saml/metadata
Tallicia Mar 13, 2024
56d7cec
fix: handle case when Servlet Path is null and ensures test WithHttp…
Tallicia Mar 13, 2024
fbd23c9
feat: reliably serve SAML SP metadata
peterhaochen47 Mar 20, 2024
81a12a4
Ignore failing SAML test
peterhaochen47 Mar 20, 2024
236a34c
disable docs test that shouldn't be running
swalchemist Mar 25, 2024
044b790
Ignore failing SAML test
swalchemist Mar 26, 2024
d8d2bfd
refactor: shorten the dummy IDP metadata
swalchemist Mar 26, 2024
89f268f
fix: "invalid XML" error in tests
peterhaochen47 Mar 26, 2024
c572972
wip: configure some metadata params
peterhaochen47 Mar 26, 2024
5fcd361
disable failing test
swalchemist Apr 1, 2024
a5fa5d8
WIP
bruce-ricard Apr 2, 2024
a4fdec9
wip
bruce-ricard Apr 4, 2024
2c2cfc9
wip: ensuring the endpoint for metadata works both in forward and dir…
Tallicia Apr 9, 2024
82d048b
add metadata redirect test
bruce-ricard Apr 11, 2024
f3655b5
wip: ensuring the saml metadata endpoint for metadata works in Mock M…
Tallicia Apr 16, 2024
5ea4e2b
wip: entityID assertion works in testSamlMetadataDefault
swalchemist Apr 16, 2024
fe0ec2d
feat: entity_id assertion passes
swalchemist Apr 16, 2024
c6f79af
wip: use working metadata path temporarily
swalchemist Apr 16, 2024
5883f8e
wip: xml refactor
swalchemist Apr 16, 2024
900c423
wip: updating to non forwarding for /saml/metadata to the example def…
Tallicia Apr 16, 2024
e4d72f7
wip: Ensuring the WantsAssertionSigned and AuthnRequestsSigned are po…
Tallicia Apr 18, 2024
8aa2fd9
wip: Adding in signature elements for SAML metadata.xml endpoint payload
Tallicia Apr 18, 2024
7839fa2
wip: Adding in signature elements for SAML metadata.xml endpoint payload
Tallicia Apr 19, 2024
f1fb4ec
feat: populate SAMP SP metadata fields: entityID, NameIDFormat, Authn…
duanemay Apr 22, 2024
d344e43
refactor: clean up commented out code
peterhaochen47 Apr 22, 2024
59b6605
Ignore non-functioning SAML tests
peterhaochen47 Apr 22, 2024
1fd65d9
Update opensaml libraries to 4.x
duanemay Apr 23, 2024
32607ed
Refactor annotations and formatting
duanemay Apr 23, 2024
6800b09
Refactor tests: formatting, andExpectAll and assertThat
duanemay Apr 23, 2024
8dcdfd6
Change from SAML XML to Java Config
duanemay Apr 23, 2024
f42f575
feat: populate sp metadata field WantAssertionsSigned
duanemay Apr 23, 2024
a9debd7
feat: saml sp metadata field - signing cert
peterhaochen47 Apr 24, 2024
0f259fc
feat: saml sp metadata encryption cert
peterhaochen47 Apr 24, 2024
7861a78
refactor: consolidate saml sp configs
peterhaochen47 Apr 24, 2024
1fa24ad
refactor: use lombok
peterhaochen47 Apr 24, 2024
a43bacd
refactor: simplify lombok annotation
peterhaochen47 Apr 24, 2024
c29b447
fix: maintain existing saml sp metadata file name
peterhaochen47 Apr 24, 2024
0e9837a
fix: saml sp metadata test set up
peterhaochen47 Apr 25, 2024
09685a8
fix: SAML SP metadata endpoint and its https redirect
hsinn0 Apr 30, 2024
2daf1bc
Clean up unnecssary codes
hsinn0 Apr 30, 2024
e4de3eb
Load the Saml Provider Data
hsinn0 May 1, 2024
a4a37a9
refactor: Spring Annotations on SamlRelyingPartyRegistrationRepository
duanemay May 7, 2024
b075cbd
fix: multiple versions of the opensaml library
duanemay May 8, 2024
c3a2068
feat: send SAML authn request to IDP
peterhaochen47 May 10, 2024
6fbbdaf
update saml link on login page
duanemay May 13, 2024
8eb263a
fix: issue with 2 JsonObjects imported
duanemay May 14, 2024
7d75dff
Merge SamlConfigProps to single class
duanemay May 14, 2024
88f9e4a
Update SamlLoginIT
duanemay May 14, 2024
da67d4d
feat: Saml Login redirects to IDP
duanemay May 14, 2024
cb31d22
fix: click first saml link matching text
duanemay May 17, 2024
2054d0f
feat: AssertionConsumerService SAML user login
duanemay May 22, 2024
00665f9
Clean up and reenable tests
duanemay May 29, 2024
44a8d57
Improve Testing of SAML Request/Response
duanemay Jun 3, 2024
a3fc3f6
Break up AuthProvider
duanemay Jun 11, 2024
538233f
Pull in OpenSaml4AuthenticationProvider
duanemay Jun 17, 2024
f2d6a42
Verify user attributes, roles, user name, email extraction
duanemay Jun 24, 2024
8f3bc78
Add editor and lombok config
duanemay Jun 24, 2024
6d6beea
Run kill_uaa as part of integrationTests
duanemay Jun 24, 2024
48a6cc1
Annotate Disabled tests with more information
duanemay Jun 25, 2024
0fe1b04
feat: SAML Logout
duanemay Jun 27, 2024
5ae1b3e
fix Selenium HomePage can be one of two urls.
duanemay Jul 5, 2024
5455ef6
Update BootstrapTests
duanemay Jul 5, 2024
f331940
feature: Zone-aware SAML SP metadata
hsinn0 Jul 5, 2024
52a4894
Disable `findByRegistrationIdWhenNoneFound` test as the assertion is …
hsinn0 Jul 5, 2024
eb5baeb
Update counter script
duanemay Jul 8, 2024
cdc6590
Update IdentityZone related classes and tests
duanemay Jul 8, 2024
748f5f2
feat: basic SAML SP metadata for non-default ID zone
duanemay Jul 8, 2024
a21cd27
wip: zoned metadata fixes and zoned login
peterhaochen47 Jul 12, 2024
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
1,815 changes: 1,815 additions & 0 deletions .editorconfig

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ buildscript {
classpath(libraries.testRetryPlugin)
classpath(libraries.gradleJcocoPlugin)
classpath(libraries.sonarqubePlugin)
//classpath(libraries.shadowPlugin)
}
}

Expand Down Expand Up @@ -64,6 +65,24 @@ subprojects {
exclude(group: "org.apache.directory.server", module: "apacheds-protocol-ldap")
exclude(group: "org.skyscreamer", module: "jsonassert")
exclude(group: "com.vaadin.external.google", module: "android-json")
exclude(group: "com.unboundid.components", module: "json")

// Exclude opensaml-security-api and non-FIPS bouncycastle libs, and use Shadow library for FIPS compliance
exclude(group: "org.bouncycastle", module: "bcpkix-jdk15on")
exclude(group: "org.bouncycastle", module: "bcprov-jdk15on")
exclude(group: "org.bouncycastle", module: "bcutil-jdk15on")
exclude(group: "org.bouncycastle", module: "bcprov-jdk18on")
exclude(group: "org.bouncycastle", module: "bcpkix-jdk18on")
exclude(group: "org.bouncycastle", module: "bcutil-jdk18on")

resolutionStrategy {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.group == 'org.opensaml' && details.requested.name.startsWith("opensaml-")) {
details.useVersion "${versions.opensaml}"
details.because 'Spring Security 5.8.x allows OpenSAML 3 or 4. OpenSAML 3 has reached its end-of-life. Spring Security 6 drops support for 3, using 4.'
}
}
}
}

dependencies {
Expand Down
16 changes: 11 additions & 5 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@ ext {
// Versions shared between multiple dependencies
versions.aspectJVersion = "1.9.4"
versions.apacheDsVersion = "2.0.0.AM27"
versions.bouncyCastleVersion = "1.0.2.5"
versions.bouncyCastleFipsVersion = "1.0.2.5"
versions.bouncyCastlePkixFipsVersion = "1.0.7"
versions.bouncyCastleTlsFipsVersion = "1.0.19"
versions.hamcrestVersion = "2.2"
versions.springBootVersion = "2.7.18"
versions.springFrameworkVersion = "5.3.37"
versions.springSecurityVersion = "5.8.13"
versions.springSecuritySamlVersion = "1.0.10.RELEASE"
versions.tomcatCargoVersion = "9.0.91"
versions.guavaVersion = "33.2.1-jre"
versions.seleniumVersion = "4.18.1"
versions.braveVersion = "6.0.3"
versions.jacksonVersion = "2.17.2"
versions.jsonPathVersion = "2.9.0"
versions.opensaml = "4.0.1" // Spring Security 5.8.x allows OpenSAML 3 or 4. OpenSAML 3 has reached its end-of-life. Spring Security 6 drops support for 3, using 4.

// 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["mariadb.version"] = "2.7.12" // Bumping to v3 breaks some pipeline jobs (and compatibility with Amazon Aurora MySQL), so pinning to v2 for now. v2 (current version) is stable and will be supported until about September 2025 (https://mariadb.com/kb/en/about-mariadb-connector-j/).
Expand All @@ -43,8 +45,9 @@ libraries.apacheDsProtocolLdap = "org.apache.directory.server:apacheds-protocol-
libraries.apacheLdapApi = "org.apache.directory.api:api-ldap-model:2.1.6"
libraries.aspectJRt = "org.aspectj:aspectjrt"
libraries.aspectJWeaver = "org.aspectj:aspectjweaver"
libraries.bouncyCastlePkix = "org.bouncycastle:bcpkix-fips:1.0.7"
libraries.bouncyCastleProv = "org.bouncycastle:bc-fips:${versions.bouncyCastleVersion}"
libraries.bouncyCastlePkixFips = "org.bouncycastle:bcpkix-fips:${versions.bouncyCastlePkixFipsVersion}"
libraries.bouncyCastleFipsProv = "org.bouncycastle:bc-fips:${versions.bouncyCastleFipsVersion}"
libraries.bouncyCastleTlsFips = "org.bouncycastle:bctls-fips:${versions.bouncyCastleTlsFipsVersion}"
libraries.braveInstrumentationSpringWebmvc = "io.zipkin.brave:brave-instrumentation-spring-webmvc:${versions.braveVersion}"
libraries.braveContextSlf4j = "io.zipkin.brave:brave-context-slf4j:${versions.braveVersion}"
libraries.commonsCodec = "commons-codec:commons-codec:1.17.0"
Expand Down Expand Up @@ -78,6 +81,7 @@ libraries.lombok = "org.projectlombok:lombok"
libraries.mariaJdbcDriver = "org.mariadb.jdbc:mariadb-java-client"
libraries.mockito = "org.mockito:mockito-core"
libraries.mockitoJunit5 = "org.mockito:mockito-junit-jupiter"
libraries.openSamlApi = "org.opensaml:opensaml-saml-api:${versions.opensaml}"
libraries.passay = "org.passay:passay:1.6.4"
libraries.postgresql = "org.postgresql:postgresql:42.7.3"
libraries.selenium = "org.seleniumhq.selenium:selenium-java:${versions.seleniumVersion}"
Expand All @@ -103,7 +107,7 @@ libraries.springRetry = "org.springframework.retry:spring-retry"
libraries.springSecurityConfig = "org.springframework.security:spring-security-config:${versions.springSecurityVersion}"
libraries.springSecurityCore = "org.springframework.security:spring-security-core:${versions.springSecurityVersion}"
libraries.springSecurityLdap = "org.springframework.security:spring-security-ldap:${versions.springSecurityVersion}"
libraries.springSecuritySaml = "org.springframework.security.extensions:spring-security-saml2-core:${versions.springSecuritySamlVersion}"
libraries.springSecuritySamlServiceProvider = "org.springframework.security:spring-security-saml2-service-provider:${versions.springSecurityVersion}"
libraries.springSecurityTaglibs = "org.springframework.security:spring-security-taglibs:${versions.springSecurityVersion}"
libraries.springSecurityTest = "org.springframework.security:spring-security-test:${versions.springSecurityVersion}"
libraries.springSecurityWeb = "org.springframework.security:spring-security-web:${versions.springSecurityVersion}"
Expand All @@ -127,6 +131,7 @@ libraries.velocity = "org.apache.velocity:velocity-engine-core:2.3"
libraries.xerces = "xerces:xercesImpl:2.12.2"
libraries.nimbusJwt = "com.nimbusds:nimbus-jose-jwt:9.40"
libraries.xmlSecurity = "org.apache.santuario:xmlsec:4.0.2"
libraries.xmlUnit = "org.xmlunit:xmlunit-assertj:2.10.0"
libraries.orgJson = "org.json:json:20240303"
libraries.owaspEsapi = "org.owasp.esapi:esapi:2.5.4.0"
libraries.jodaTime = "joda-time:joda-time:2.12.7"
Expand All @@ -139,3 +144,4 @@ libraries.springBootGradlePlugin = "org.springframework.boot:spring-boot-gradle-
libraries.springDependencyMangementGradlePlugin = "io.spring.gradle:dependency-management-plugin"
libraries.gradleJcocoPlugin = "org.barfuin.gradle.jacocolog:gradle-jacoco-log:3.1.0"
libraries.sonarqubePlugin = "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:5.1.0.4882"
//libraries.shadowPlugin = "com.github.johnrengelman:shadow:8.1.1"
1 change: 1 addition & 0 deletions lombok.config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lombok.addLombokGeneratedAnnotation = true
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import lombok.Getter;
import org.cloudfoundry.identity.uaa.EntityWithAlias;
import org.cloudfoundry.identity.uaa.util.JsonUtils;
import org.springframework.util.StringUtils;
Expand All @@ -44,6 +44,7 @@
import static org.cloudfoundry.identity.uaa.util.JsonUtils.getNodeAsInt;
import static org.cloudfoundry.identity.uaa.util.JsonUtils.getNodeAsString;

@Getter
@JsonSerialize(using = IdentityProvider.IdentityProviderSerializer.class)
@JsonDeserialize(using = IdentityProvider.IdentityProviderDeserializer.class)
public class IdentityProvider<T extends AbstractIdentityProviderDefinition> implements EntityWithAlias {
Expand Down Expand Up @@ -78,99 +79,77 @@ public class IdentityProvider<T extends AbstractIdentityProviderDefinition> impl
private String identityZoneId;
private String aliasId;
private String aliasZid;
public Date getCreated() {
return created;
}
@JsonIgnore
private boolean serializeConfigRaw;

public IdentityProvider setCreated(Date created) {
public IdentityProvider<T> setCreated(Date created) {
this.created = created;
return this;
}

public Date getLastModified() {
return lastModified;
}

public IdentityProvider setLastModified(Date lastModified) {
public IdentityProvider<T> setLastModified(Date lastModified) {
this.lastModified = lastModified;
return this;
}

public IdentityProvider setVersion(int version) {
public IdentityProvider<T> setVersion(int version) {
this.version = version;
return this;
}

public int getVersion() {
return version;
}

public String getName() {
return name;
}

public IdentityProvider setName(String name) {
public IdentityProvider<T> setName(String name) {
this.name = name;
return this;
}

@Override
public String getId() {
return id;
public IdentityProvider<T> setId(String id) {
this.id = id;
return this;
}

@Override
public String getZoneId() {
return getIdentityZoneId();
}

public IdentityProvider setId(String id) {
this.id = id;
return this;
}

public T getConfig() {
return config;
}

public IdentityProvider setConfig(T config) {
if (config == null) {
this.type = UNKNOWN;
} else {
Class clazz = config.getClass();
if (SamlIdentityProviderDefinition.class.isAssignableFrom(clazz)) {
this.type = SAML;
public IdentityProvider<T> setConfig(T config) {
this.type = UNKNOWN;
if (config != null) {
this.type = determineType(config.getClass());
if (SAML.equals(this.type)) {
if (StringUtils.hasText(getOriginKey())) {
((SamlIdentityProviderDefinition) config).setIdpEntityAlias(getOriginKey());
}
if (StringUtils.hasText(getIdentityZoneId())) {
((SamlIdentityProviderDefinition) config).setZoneId(getIdentityZoneId());
}
} else if (UaaIdentityProviderDefinition.class.isAssignableFrom(clazz)) {
this.type = UAA;
} else if (RawExternalOAuthIdentityProviderDefinition.class.isAssignableFrom(clazz)) {
this.type = OAUTH20;
} else if (OIDCIdentityProviderDefinition.class.isAssignableFrom(clazz)) {
this.type = OIDC10;
} else if (LdapIdentityProviderDefinition.class.isAssignableFrom(clazz)) {
this.type = LDAP;
} else if (KeystoneIdentityProviderDefinition.class.isAssignableFrom(clazz)) {
this.type = KEYSTONE;
} else if (AbstractIdentityProviderDefinition.class.isAssignableFrom(clazz)) {
this.type = UNKNOWN;
} else {
throw new IllegalArgumentException("Unknown identity provider configuration type:" + clazz.getName());
}
}
this.config = config;
return this;
}

public String getOriginKey() {
return originKey;
private static String determineType(Class clazz) {
if (SamlIdentityProviderDefinition.class.isAssignableFrom(clazz)) {
return SAML;
} else if (UaaIdentityProviderDefinition.class.isAssignableFrom(clazz)) {
return UAA;
} else if (RawExternalOAuthIdentityProviderDefinition.class.isAssignableFrom(clazz)) {
return OAUTH20;
} else if (OIDCIdentityProviderDefinition.class.isAssignableFrom(clazz)) {
return OIDC10;
} else if (LdapIdentityProviderDefinition.class.isAssignableFrom(clazz)) {
return LDAP;
} else if (KeystoneIdentityProviderDefinition.class.isAssignableFrom(clazz)) {
return KEYSTONE;
} else if (AbstractIdentityProviderDefinition.class.isAssignableFrom(clazz)) {
return UNKNOWN;
} else {
throw new IllegalArgumentException("Unknown identity provider configuration type:" + clazz.getName());
}
}

public IdentityProvider setOriginKey(String originKey) {
public IdentityProvider<T> setOriginKey(String originKey) {
this.originKey = originKey;
if (config != null && config instanceof SamlIdentityProviderDefinition) {
((SamlIdentityProviderDefinition) config).setIdpEntityAlias(originKey);
Expand All @@ -179,51 +158,29 @@ public IdentityProvider setOriginKey(String originKey) {
return this;
}

public String getType() {
return type;
}

public IdentityProvider setType(String type) {
public IdentityProvider<T> setType(String type) {
this.type = type;
return this;
}

public boolean isActive() {
return active;
}

public IdentityProvider setActive(boolean active) {
public IdentityProvider<T> setActive(boolean active) {
this.active = active;
return this;
}

public String getIdentityZoneId() {
return identityZoneId;
}

public IdentityProvider setIdentityZoneId(String identityZoneId) {
public IdentityProvider<T> setIdentityZoneId(String identityZoneId) {
this.identityZoneId = identityZoneId;
if (config != null && config instanceof SamlIdentityProviderDefinition) {
((SamlIdentityProviderDefinition) config).setZoneId(identityZoneId);
}
return this;
}

@Override
public String getAliasId() {
return aliasId;
}

@Override
public void setAliasId(String aliasId) {
this.aliasId = aliasId;
}

@Override
public String getAliasZid() {
return aliasZid;
}

@Override
public void setAliasZid(String aliasZid) {
this.aliasZid = aliasZid;
Expand Down Expand Up @@ -304,9 +261,7 @@ public boolean equals(Object obj) {
} else if (!aliasZid.equals(other.aliasZid)) {
return false;
}
if (version != other.version)
return false;
return true;
return version == other.version;
}

@Override
Expand Down Expand Up @@ -344,13 +299,6 @@ public String toString() {
return sb.toString();
}

private boolean serializeConfigRaw;

@JsonIgnore
public boolean isSerializeConfigRaw() {
return serializeConfigRaw;
}

@JsonIgnore
public void setSerializeConfigRaw(boolean serializeConfigRaw) {
this.serializeConfigRaw = serializeConfigRaw;
Expand Down Expand Up @@ -446,8 +394,5 @@ public IdentityProvider deserialize(JsonParser jp, DeserializationContext ctxt)
result.setAliasZid(getNodeAsString(node, FIELD_ALIAS_ZID, null));
return result;
}


}

}
Loading
Loading