Skip to content

Commit

Permalink
Merge branch 'develop' into feature/add-alias-id-and-alias-zid-fields…
Browse files Browse the repository at this point in the history
…-to-scimuser
  • Loading branch information
adrianhoelzl-sap committed Mar 11, 2024
2 parents a951797 + 500228c commit 02bd32b
Show file tree
Hide file tree
Showing 21 changed files with 837 additions and 288 deletions.
4 changes: 2 additions & 2 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ versions.tomcatCargoVersion = "9.0.86"
versions.guavaVersion = "33.0.0-jre"
versions.seleniumVersion = "4.18.1"
versions.braveVersion = "6.0.2"
versions.jacksonVersion = "2.16.1"
versions.jacksonVersion = "2.16.2"
versions.jsonPathVersion = "2.9.0"

// 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)
Expand Down Expand Up @@ -50,7 +50,7 @@ libraries.braveInstrumentationSpringWebmvc = "io.zipkin.brave:brave-instrumentat
libraries.braveContextSlf4j = "io.zipkin.brave:brave-context-slf4j:${versions.braveVersion}"
libraries.commonsIo = "commons-io:commons-io:2.15.1"
libraries.dumbster = "dumbster:dumbster:1.6"
libraries.eclipseJgit = "org.eclipse.jgit:org.eclipse.jgit:6.8.0.202311291450-r"
libraries.eclipseJgit = "org.eclipse.jgit:org.eclipse.jgit:6.9.0.202403050737-r"
libraries.flywayCore = "org.flywaydb:flyway-core"
libraries.greenmail = "com.icegreen:greenmail:1.6.15"
libraries.guava = "com.google.guava:guava:${versions.guavaVersion}"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package org.cloudfoundry.identity.uaa.health;

import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import java.sql.Connection;
import java.sql.Statement;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;

/**
* Simple controller that just returns "ok" in a request body for the purposes
* of monitoring health of the application. It also registers a shutdown hook
Expand All @@ -18,10 +23,13 @@
public class HealthzEndpoint {
private static Logger logger = LoggerFactory.getLogger(HealthzEndpoint.class);
private volatile boolean stopping = false;
private volatile Boolean wasLastConnectionSuccessful = null;
private DataSource dataSource;

public HealthzEndpoint(
@Value("${uaa.shutdown.sleep:10000}") final long sleepTime,
final Runtime runtime) {
final Runtime runtime,
final DataSource dataSource) {
Thread shutdownHook = new Thread(() -> {
stopping = true;
logger.warn("Shutdown hook received, future requests to this endpoint will return 503");
Expand All @@ -35,6 +43,7 @@ public HealthzEndpoint(
}
});
runtime.addShutdownHook(shutdownHook);
this.dataSource = dataSource;
}

@GetMapping("/healthz")
Expand All @@ -45,8 +54,28 @@ public String getHealthz(HttpServletResponse response) {
response.setStatus(503);
return "stopping\n";
} else {
return "ok\n";
if (wasLastConnectionSuccessful == null) {
return "UAA running. Database status unknown.\n";
}

if (wasLastConnectionSuccessful) {
return "ok\n";
} else {
response.setStatus(503);
return "Database Connection failed.\n";
}
}
}

}
@Scheduled(fixedRateString = "${uaa.health.db.rate:10000}")
void isDataSourceConnectionAvailable() {
try (Connection c = dataSource.getConnection(); Statement statement = c.createStatement()) {
statement.execute("SELECT 1 from identity_zone;"); //"SELECT 1;" Not supported by HSQLDB
wasLastConnectionSuccessful = true;
return;
} catch (Exception ex) {
logger.error("Could not establish connection to DB - " + ex.getMessage());
}
wasLastConnectionSuccessful = false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
public class BuildInfo implements InitializingBean {
private final Logger logger = LoggerFactory.getLogger(getClass());

@Value("${uaa.url:http://localhost:8080/uaa}")
@Value("${uaa.url:#{T(org.cloudfoundry.identity.uaa.util.UaaStringUtils).DEFAULT_UAA_URL}}")
private String uaaUrl;
private String version;
private String commitId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ public class LogSanitizerUtil {

public static final String SANITIZED_FLAG = "[SANITIZED]";

private LogSanitizerUtil() {
}

@Nullable
public static String sanitize(String original) {
if (original == null) return original;
if (original == null) return null;

String cleaned = original.replace("\r","|")
.replace("\n","|")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package org.cloudfoundry.identity.uaa.logging;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
* Returns Log instance that replaces \n, \r, \t with a | to prevent log forging.
*/
public class SanitizedLogFactory {

private SanitizedLogFactory() { }

public static SanitizedLog getLog(Class<?> clazz) {
return new SanitizedLog(LoggerFactory.getLogger(clazz));
return new SanitizedLog(LogManager.getLogger(clazz));
}

public static class SanitizedLog {
Expand All @@ -24,19 +26,63 @@ public boolean isDebugEnabled() {
}

public void info(String message) {
fallback.info(LogSanitizerUtil.sanitize(message));
if (fallback.isInfoEnabled()) {
fallback.info(LogSanitizerUtil.sanitize(message));
}
}

public void info(String message, Throwable t) {
if (fallback.isInfoEnabled()) {
fallback.info(LogSanitizerUtil.sanitize(message), t);
}
}

public void warn(String message) {
fallback.warn(LogSanitizerUtil.sanitize(message));
if (fallback.isWarnEnabled()) {
fallback.warn(LogSanitizerUtil.sanitize(message));
}
}

public void warn(String message, Throwable t) {
if (fallback.isWarnEnabled()) {
fallback.warn(LogSanitizerUtil.sanitize(message), t);
}
}

public void debug(String message) {
fallback.debug(LogSanitizerUtil.sanitize(message));
if (fallback.isDebugEnabled()) {
fallback.debug(LogSanitizerUtil.sanitize(message));
}
}

public void debug(String message, Throwable t) {
fallback.debug(LogSanitizerUtil.sanitize(message), t);
if (fallback.isDebugEnabled()) {
fallback.debug(LogSanitizerUtil.sanitize(message), t);
}
}

public void error(String message) {
if (fallback.isErrorEnabled()) {
fallback.error(LogSanitizerUtil.sanitize(message));
}
}

public void error(String message, Throwable t) {
if (fallback.isErrorEnabled()) {
fallback.error(LogSanitizerUtil.sanitize(message), t);
}
}

public void trace(String message) {
if (fallback.isTraceEnabled()) {
fallback.trace(LogSanitizerUtil.sanitize(message));
}
}

public void trace(String message, Throwable t) {
if (fallback.isTraceEnabled()) {
fallback.trace(LogSanitizerUtil.sanitize(message), t);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
Expand Down Expand Up @@ -88,26 +89,30 @@ private AbstractExternalOAuthIdentityProviderDefinition getExternalOIDCIdentityP
idpDefinitionMap.get("passwordGrantEnabled") == null ? false : (boolean) idpDefinitionMap.get("passwordGrantEnabled"));
oidcIdentityProviderDefinition.setSetForwardHeader(idpDefinitionMap.get("setForwardHeader") == null ? false : (boolean) idpDefinitionMap.get("passwordGrantEnabled"));
oidcIdentityProviderDefinition.setPrompts((List<Prompt>) idpDefinitionMap.get("prompts"));
setJwtClientAuthentication("jwtclientAuthentication", idpDefinitionMap, oidcIdentityProviderDefinition);
setJwtClientAuthentication(idpDefinitionMap, oidcIdentityProviderDefinition);
oauthIdpDefinitions.put(alias, oidcIdentityProviderDefinition);
rawDef = oidcIdentityProviderDefinition;
provider.setType(OriginKeys.OIDC10);
return rawDef;
}

private static void setJwtClientAuthentication(String entry, Map<String, Object> map, OIDCIdentityProviderDefinition definition) {
if (map.get(entry) != null) {
if (map.get(entry) instanceof Boolean) {
boolean jwtClientAuthentication = (Boolean) map.get(entry);
if (jwtClientAuthentication) {
definition.setJwtClientAuthentication(new HashMap<>());
private static void setJwtClientAuthentication(Map<String, Object> map, OIDCIdentityProviderDefinition definition) {
Object jwtClientAuthDetails = getJwtClientAuthenticationDetails(map, List.of("jwtClientAuthentication", "jwtclientAuthentication"));
if (jwtClientAuthDetails != null) {
if (jwtClientAuthDetails instanceof Boolean boolValue) {
if (boolValue.booleanValue()) {
definition.setJwtClientAuthentication(Collections.emptyMap());
}
} else if (map.get(entry) instanceof HashMap) {
definition.setJwtClientAuthentication(map.get(entry));
} else if (jwtClientAuthDetails instanceof Map) {
definition.setJwtClientAuthentication(jwtClientAuthDetails);
}
}
}

private static Object getJwtClientAuthenticationDetails(Map<String, Object> uaaYamlMap, List<String> entryInUaaYaml) {
return entryInUaaYaml.stream().filter(e -> uaaYamlMap.get(e) != null).findFirst().map(uaaYamlMap::get).orElse(null);
}

public static IdentityProviderWrapper getIdentityProviderWrapper(String origin, AbstractExternalOAuthIdentityProviderDefinition rawDef, IdentityProvider provider, boolean override) {
provider.setOriginKey(origin);
provider.setName("UAA Oauth Identity Provider["+provider.getOriginKey()+"]");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public abstract class AbstractQueryable<T> implements Queryable<T> {

private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

private JdbcPagingListFactory pagingListFactory;
protected final JdbcPagingListFactory pagingListFactory;

protected RowMapper<T> rowMapper;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.cloudfoundry.identity.uaa.util.AlphanumericRandomValueStringGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
Expand Down Expand Up @@ -125,9 +126,12 @@ private String generateParameterPrefix(String filter) {
}
}

/**
* @return the WHERE and (optional) ORDER BY clauses WITHOUT the "WHERE" keyword in the beginning
*/
private String getWhereClause(
final String filter,
final String sortBy,
@Nullable final String filter,
@Nullable final String sortBy,
final boolean ascending,
final Map<String, Object> values,
final AttributeNameMapper mapper,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ public interface ScimUserProvisioning extends ResourceManager<ScimUser>, Queryab

List<ScimUser> retrieveByUsernameAndZone(String username, String zoneId);

/**
* Retrieve all users that satisfy the given SCIM filter and stem from active IdPs.
*/
List<ScimUser> retrieveByScimFilterOnlyActive(
String filter,
String sortBy,
boolean ascending,
String zoneId
);

List<ScimUser> retrieveByUsernameAndOriginAndZone(String username, String origin, String zoneId);

void changePassword(String id, String oldPassword, String newPassword, String zoneId) throws ScimResourceNotFoundException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@
import static org.cloudfoundry.identity.uaa.codestore.ExpiringCodeType.REGISTRATION;
import static org.springframework.util.StringUtils.isEmpty;

import lombok.Getter;

/**
* User provisioning and query endpoints. Implements the core API from the
* Simple Cloud Identity Management (SCIM)
Expand Down Expand Up @@ -120,6 +122,7 @@ public class ScimUserEndpoints implements InitializingBean, ApplicationEventPubl
private final ExpiringCodeStore codeStore;
private final ApprovalStore approvalStore;
private final ScimGroupMembershipManager membershipManager;
@Getter
private final int userMaxCount;
private final HttpMessageConverter<?>[] messageConverters;
private final AtomicInteger scimUpdates;
Expand Down
Loading

0 comments on commit 02bd32b

Please sign in to comment.