Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/develop' into new-s…
Browse files Browse the repository at this point in the history
…aml-0530

# Conflicts:
#	model/src/main/java/org/cloudfoundry/identity/uaa/provider/SamlIdentityProviderDefinition.java
#	server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/BootstrapSamlIdentityProviderData.java
#	server/src/main/java/org/cloudfoundry/identity/uaa/provider/saml/SamlIdentityProviderConfigurator.java
#	server/src/test/java/org/cloudfoundry/identity/uaa/config/IdentityProviderBootstrapTest.java
#	server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/BootstrapSamlIdentityProviderDataTests.java
#	server/src/test/java/org/cloudfoundry/identity/uaa/provider/saml/SamlIdentityProviderConfiguratorTests.java
  • Loading branch information
strehle committed Jul 16, 2024
2 parents c1a3677 + 8ba95b2 commit 114af0c
Show file tree
Hide file tree
Showing 27 changed files with 326 additions and 44 deletions.
4 changes: 2 additions & 2 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ ext {
}

// Dependencies (some rely on shared versions, some are shared between projects)
libraries.apacheCommonsRngCore = "org.apache.commons:commons-rng-core:1.5"
libraries.apacheCommonsRngSimple = "org.apache.commons:commons-rng-simple:1.5"
libraries.apacheCommonsRngCore = "org.apache.commons:commons-rng-core:1.6"
libraries.apacheCommonsRngSimple = "org.apache.commons:commons-rng-simple:1.6"
libraries.apacheCommonsText = "org.apache.commons:commons-text:1.12.0"
libraries.apacheDsProtocolLdap = "org.apache.directory.server:apacheds-protocol-ldap:${versions.apacheDsVersion}"
libraries.apacheLdapApi = "org.apache.directory.api:api-ldap-model:2.1.6"
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
5 changes: 4 additions & 1 deletion gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

##############################################################################
#
Expand Down Expand Up @@ -84,7 +86,8 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
Expand Down
2 changes: 2 additions & 0 deletions gradlew.bat
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem

@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public class SamlIdentityProviderDefinition extends ExternalIdentityProviderDefi
private boolean skipSslValidation = false;
private List<String> authnContext;

@JsonIgnore
private String idpEntityId;

public SamlIdentityProviderDefinition() {
}

Expand All @@ -61,6 +64,7 @@ public SamlIdentityProviderDefinition clone() {
SamlIdentityProviderDefinition def = new SamlIdentityProviderDefinition();
def.setMetaDataLocation(metaDataLocation);
def.setIdpEntityAlias(idpEntityAlias);
def.setIdpEntityId(idpEntityId);
def.setZoneId(zoneId);
def.setNameID(nameID);
def.setAssertionConsumerIndex(assertionConsumerIndex);
Expand Down Expand Up @@ -108,6 +112,17 @@ public static MetadataLocation getType(String urlOrXmlData) {
return MetadataLocation.UNKNOWN;
}

@JsonIgnore
public String getIdpEntityId() {
return this.idpEntityId;
}

@JsonIgnore
public void setIdpEntityId(final String idpEntityId) {
this.idpEntityId = idpEntityId;
}

private boolean validateXml(String xml) {
private static boolean validateXml(String xml) {
if (xml == null || xml.toUpperCase().contains("<!DOCTYPE")) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public class UserConfig {

private boolean checkOriginEnabled;

private boolean allowOriginLoop = true;

public List<String> getDefaultGroups() {
return defaultGroups;
}
Expand Down Expand Up @@ -78,4 +80,12 @@ public boolean isCheckOriginEnabled() {
public void setCheckOriginEnabled(boolean checkOriginEnabled) {
this.checkOriginEnabled = checkOriginEnabled;
}

public boolean isAllowOriginLoop() {
return this.allowOriginLoop;
}

public void setAllowOriginLoop(final boolean allowAllOrigins) {
this.allowOriginLoop = allowAllOrigins;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,13 @@ public void testSetIdpEntityAlias() {
def.setIdpEntityAlias("testalias");
}

@Test
public void testSetIdpEntityId() {
SamlIdentityProviderDefinition def = new SamlIdentityProviderDefinition();
def.setIdpEntityId("testalias");
assertEquals("testalias", def.getIdpEntityId());
}

@Test
public void testSetEmailDomain() {
SamlIdentityProviderDefinition def = new SamlIdentityProviderDefinition();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.List;
Expand Down Expand Up @@ -60,4 +61,19 @@ public void setMaxUsers() {
userConfig.setMaxUsers(100);
assertEquals(100, userConfig.getMaxUsers());
}

@Test
public void testDefaultOrigin() {
UserConfig userConfig = new UserConfig();
assertTrue(userConfig.isAllowOriginLoop());
assertFalse(userConfig.isCheckOriginEnabled());
}

@Test
public void testOriginLoop() {
UserConfig userConfig = new UserConfig();
assertTrue(userConfig.isAllowOriginLoop());
userConfig.setAllowOriginLoop(false);
assertFalse(userConfig.isCheckOriginEnabled());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ public ResponseEntity<IdentityProvider> createIdentityProvider(@RequestBody Iden
SamlIdentityProviderDefinition definition = ObjectUtils.castInstance(body.getConfig(), SamlIdentityProviderDefinition.class);
definition.setZoneId(zoneId);
definition.setIdpEntityAlias(body.getOriginKey());
samlConfigurator.validateSamlIdentityProviderDefinition(definition);
definition.setIdpEntityId(samlConfigurator.validateSamlIdentityProviderDefinition(definition, true));
body.setConfig(definition);
}

Expand Down Expand Up @@ -223,7 +223,7 @@ public ResponseEntity<IdentityProvider> updateIdentityProvider(@PathVariable Str
SamlIdentityProviderDefinition definition = ObjectUtils.castInstance(body.getConfig(), SamlIdentityProviderDefinition.class);
definition.setZoneId(zoneId);
definition.setIdpEntityAlias(body.getOriginKey());
samlConfigurator.validateSamlIdentityProviderDefinition(definition);
samlConfigurator.validateSamlIdentityProviderDefinition(definition, false);
body.setConfig(definition);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public interface IdentityProviderProvisioning {

IdentityProvider retrieveByOrigin(String origin, String zoneId);

IdentityProvider retrieveByExternId(String externId, String type, String zoneId);

default IdentityProvider retrieveByOriginIgnoreActiveFlag(String origin, String zoneId) {
return retrieveByOrigin(origin, zoneId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,25 @@
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Component("identityProviderProvisioning")
public class JdbcIdentityProviderProvisioning implements IdentityProviderProvisioning, SystemDeletable {

private static Logger logger = LoggerFactory.getLogger(JdbcIdentityProviderProvisioning.class);

public static final String ID_PROVIDER_FIELDS = "id,version,created,lastmodified,name,origin_key,type,config,identity_zone_id,active,alias_id,alias_zid";
public static final String ID_PROVIDER_FIELDS = "id,version,created,lastmodified,name,origin_key,type,config,identity_zone_id,active,alias_id,alias_zid,external_key";

public static final String CREATE_IDENTITY_PROVIDER_SQL = "insert into identity_provider(" + ID_PROVIDER_FIELDS + ") values (?,?,?,?,?,?,?,?,?,?,?,?)";
public static final String CREATE_IDENTITY_PROVIDER_SQL = "insert into identity_provider(" + ID_PROVIDER_FIELDS + ") values (?,?,?,?,?,?,?,?,?,?,?,?,?)";

public static final String IDENTITY_PROVIDERS_QUERY = "select " + ID_PROVIDER_FIELDS + " from identity_provider where identity_zone_id=?";

public static final String IDENTITY_ACTIVE_PROVIDERS_QUERY = IDENTITY_PROVIDERS_QUERY + " and active=?";

public static final String IDP_WITH_ALIAS_EXISTS_QUERY = "select 1 from identity_provider idp where idp.identity_zone_id = ? and idp.alias_zid <> '' limit 1";

public static final String ID_PROVIDER_UPDATE_FIELDS = "version,lastmodified,name,type,config,active,alias_id,alias_zid".replace(",", "=?,") + "=?";
public static final String ID_PROVIDER_UPDATE_FIELDS = "version,lastmodified,name,type,config,active,alias_id,alias_zid,external_key".replace(",", "=?,") + "=?";

public static final String UPDATE_IDENTITY_PROVIDER_SQL = "update identity_provider set " + ID_PROVIDER_UPDATE_FIELDS + " where id=? and identity_zone_id=?";

Expand All @@ -51,6 +52,8 @@ public class JdbcIdentityProviderProvisioning implements IdentityProviderProvisi

public static final String IDENTITY_PROVIDER_BY_ORIGIN_QUERY_ACTIVE = IDENTITY_PROVIDER_BY_ORIGIN_QUERY + " and active = ? ";

public static final String IDENTITY_PROVIDER_BY_EXTERNAL_QUERY = IDENTITY_PROVIDERS_QUERY + " and type=? and external_key=?";

protected final JdbcTemplate jdbcTemplate;

private final RowMapper<IdentityProvider> mapper = new IdentityProviderRowMapper();
Expand Down Expand Up @@ -100,9 +103,14 @@ public IdentityProvider retrieveByOriginIgnoreActiveFlag(String origin, String z
return jdbcTemplate.queryForObject(IDENTITY_PROVIDER_BY_ORIGIN_QUERY, mapper, origin, zoneId);
}

@Override
public IdentityProvider retrieveByExternId(String externId, String type, String zoneId) {
return jdbcTemplate.queryForObject(IDENTITY_PROVIDER_BY_EXTERNAL_QUERY, mapper, zoneId, type, externId);
}

@Override
public IdentityProvider create(final IdentityProvider identityProvider, String zoneId) {
validate(identityProvider);
String externId = validate(identityProvider);
final String id = UUID.randomUUID().toString();
try {
jdbcTemplate.update(CREATE_IDENTITY_PROVIDER_SQL, ps -> {
Expand All @@ -118,7 +126,8 @@ public IdentityProvider create(final IdentityProvider identityProvider, String z
ps.setString(pos++, zoneId);
ps.setBoolean(pos++, identityProvider.isActive());
ps.setString(pos++, identityProvider.getAliasId());
ps.setString(pos, identityProvider.getAliasZid());
ps.setString(pos++, identityProvider.getAliasZid());
ps.setString(pos, externId);
});
} catch (DuplicateKeyException e) {
throw new IdpAlreadyExistsException(e.getMostSpecificCause().getMessage());
Expand All @@ -128,7 +137,7 @@ public IdentityProvider create(final IdentityProvider identityProvider, String z

@Override
public IdentityProvider update(final IdentityProvider identityProvider, String zoneId) {
validate(identityProvider);
String externId = validate(identityProvider);
jdbcTemplate.update(UPDATE_IDENTITY_PROVIDER_SQL, ps -> {
int pos = 1;

Expand All @@ -141,6 +150,7 @@ public IdentityProvider update(final IdentityProvider identityProvider, String z
ps.setBoolean(pos++, identityProvider.isActive());
ps.setString(pos++, identityProvider.getAliasId());
ps.setString(pos++, identityProvider.getAliasZid());
ps.setString(pos++, externId);

// placeholders in WHERE
ps.setString(pos++, identityProvider.getId().trim());
Expand All @@ -149,20 +159,25 @@ public IdentityProvider update(final IdentityProvider identityProvider, String z
return retrieve(identityProvider.getId(), zoneId);
}

protected void validate(IdentityProvider provider) {
private String validate(IdentityProvider provider) {
if (provider == null) {
throw new NullPointerException("Provider can not be null.");
}
if (!StringUtils.hasText(provider.getIdentityZoneId())) {
throw new DataIntegrityViolationException("Identity zone ID must be set.");
}
String externId = null;
//ensure that SAML IDPs have redundant fields synchronized
if (OriginKeys.SAML.equals(provider.getType()) && provider.getConfig() != null) {
SamlIdentityProviderDefinition saml = ObjectUtils.castInstance(provider.getConfig(), SamlIdentityProviderDefinition.class);
saml.setIdpEntityAlias(provider.getOriginKey());
saml.setZoneId(provider.getIdentityZoneId());
provider.setConfig(saml);
externId = saml.getIdpEntityId();
} else if (provider.getConfig() instanceof AbstractExternalOAuthIdentityProviderDefinition<?> externalOAuthIdentityProviderDefinition) {
externId = externalOAuthIdentityProviderDefinition.getIssuer();
}
return externId;
}

@Override
Expand Down Expand Up @@ -193,17 +208,25 @@ public IdentityProvider mapRow(ResultSet rs, int rowNum) throws SQLException {
identityProvider.setOriginKey(rs.getString(pos++));
identityProvider.setType(rs.getString(pos++));
String config = rs.getString(pos++);
identityProvider.setIdentityZoneId(rs.getString(pos++));
identityProvider.setActive(rs.getBoolean(pos++));
identityProvider.setAliasId(rs.getString(pos++));
identityProvider.setAliasZid(rs.getString(pos++));
String externId = rs.getString(pos);
if (StringUtils.hasText(config)) {
AbstractIdentityProviderDefinition definition;
switch (identityProvider.getType()) {
case OriginKeys.SAML:
definition = JsonUtils.readValue(config, SamlIdentityProviderDefinition.class);
Optional.ofNullable(definition).map(SamlIdentityProviderDefinition.class::cast).ifPresent(e -> e.setIdpEntityId(externId));
break;
case OriginKeys.OAUTH20:
definition = JsonUtils.readValue(config, RawExternalOAuthIdentityProviderDefinition.class);
Optional.ofNullable(definition).map(RawExternalOAuthIdentityProviderDefinition.class::cast).ifPresent(e -> e.setIssuer(externId));
break;
case OriginKeys.OIDC10:
definition = JsonUtils.readValue(config, OIDCIdentityProviderDefinition.class);
Optional.ofNullable(definition).map(OIDCIdentityProviderDefinition.class::cast).ifPresent(e -> e.setIssuer(externId));
break;
case OriginKeys.UAA:
definition = JsonUtils.readValue(config, UaaIdentityProviderDefinition.class);
Expand All @@ -222,10 +245,6 @@ public IdentityProvider mapRow(ResultSet rs, int rowNum) throws SQLException {
identityProvider.setConfig(definition);
}
}
identityProvider.setIdentityZoneId(rs.getString(pos++));
identityProvider.setActive(rs.getBoolean(pos++));
identityProvider.setAliasId(rs.getString(pos++));
identityProvider.setAliasZid(rs.getString(pos));
return identityProvider;
}
}
Expand Down
Loading

0 comments on commit 114af0c

Please sign in to comment.