Permalink
Browse files

Merge branch 'release/1.2.3'

Change-Id: I9afe76ff60e12922fa9e8c917143764798da59ba
  • Loading branch information...
2 parents 5178c99 + af4c140 commit d6a8f8780632b8755bdc645369f2b1f2d17dd54d @joeldsa joeldsa committed Oct 12, 2012
Showing with 984 additions and 425 deletions.
  1. +2 −2 common/pom.xml
  2. +4 −1 common/src/main/java/org/cloudfoundry/identity/uaa/config/YamlServletProfileInitializer.java
  3. +10 −113 common/src/main/java/org/cloudfoundry/identity/uaa/oauth/ClientAdminBootstrap.java
  4. +6 −6 ...ry/identity/uaa/oauth/{UaaAuthorizationRequestFactory.java → UaaAuthorizationRequestManager.java}
  5. +1 −1 common/src/main/java/org/cloudfoundry/identity/uaa/oauth/UaaUserApprovalHandler.java
  6. +16 −13 common/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimUserEndpoints.java
  7. +1 −1 common/src/main/java/org/cloudfoundry/identity/uaa/scim/SearchResultsFactory.java
  8. +1 −1 common/src/main/java/org/cloudfoundry/identity/uaa/scim/UserIdConversionEndpoints.java
  9. +12 −1 common/src/main/java/org/cloudfoundry/identity/uaa/security/DefaultSecurityContextAccessor.java
  10. +90 −14 common/src/main/java/org/cloudfoundry/identity/uaa/varz/VarzEndpoint.java
  11. +1 −0 common/src/test/java/org/cloudfoundry/identity/uaa/config/YamlServletProfileInitializerTests.java
  12. +38 −85 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/ClientAdminBootstrapTests.java
  13. +3 −3 ...y/uaa/oauth/{UaaAuthorizationRequestFactoryTests.java → UaaAuthorizationRequestManagerTests.java}
  14. +4 −3 common/src/test/java/org/cloudfoundry/identity/uaa/scim/ScimUserBootstrapTests.java
  15. +20 −27 common/src/test/java/org/cloudfoundry/identity/uaa/scim/ScimUserEndpointsTests.java
  16. +18 −0 common/src/test/java/org/cloudfoundry/identity/uaa/security/DefaultSecurityContextAccessorTests.java
  17. +1 −1 common/src/test/java/org/cloudfoundry/identity/uaa/varz/VarzEndpointTests.java
  18. +3 −3 gem/bin/completion-helper
  19. +1 −1 gem/lib/cli/common.rb
  20. +13 −3 gem/lib/cli/group.rb
  21. +12 −3 gem/lib/cli/user.rb
  22. +4 −7 gem/lib/uaa/token_issuer.rb
  23. +45 −27 gem/lib/uaa/user_account.rb
  24. +1 −1 gem/lib/uaa/version.rb
  25. +35 −12 gem/spec/cli_spec.rb
  26. +16 −9 gem/spec/stub_scim.rb
  27. +89 −51 gem/spec/stub_uaa.rb
  28. +25 −4 gem/spec/token_issuer_spec.rb
  29. +3 −3 pom.xml
  30. +1 −1 samples/api/pom.xml
  31. +1 −1 samples/app/pom.xml
  32. +1 −1 samples/login/pom.xml
  33. +1 −1 samples/pom.xml
  34. +1 −1 uaa/.springBeans
  35. +1 −1 uaa/pom.xml
  36. +1 −1 uaa/src/main/resources/build.properties
  37. +1 −1 uaa/src/main/resources/log4j.properties
  38. +0 −5 uaa/src/main/resources/uaa.yml
  39. +2 −3 uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml
  40. +9 −2 uaa/src/main/webapp/WEB-INF/spring/scim-endpoints.xml
  41. +434 −0 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/ScimGroupEndpointsIntegrationTests.java
  42. +55 −11 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/ScimUserEndpointsIntegrationTests.java
  43. +1 −0 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/VarzEndpointIntegrationTests.java
View
@@ -5,7 +5,7 @@
<parent>
<groupId>org.cloudfoundry.identity</groupId>
<artifactId>cloudfoundry-identity-parent</artifactId>
- <version>1.2.2</version>
+ <version>1.2.3</version>
<relativePath>..</relativePath>
</parent>
@@ -186,7 +186,7 @@
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
- <scope>runtime</scope>
+ <scope>compile</scope>
<optional>true</optional>
</dependency>
@@ -18,6 +18,7 @@
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
+import org.apache.log4j.MDC;
import org.cloudfoundry.identity.uaa.config.YamlProcessor.ResolutionMethod;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.core.env.ConfigurableEnvironment;
@@ -90,9 +91,9 @@ public void initialize(ConfigurableWebApplicationContext applicationContext) {
factory.setResources(new Resource[] { resource });
Properties properties = factory.getObject();
applySpringProfiles(properties, applicationContext.getEnvironment(), servletContext);
- applyLog4jConfiguration(properties, applicationContext.getEnvironment(), servletContext);
applicationContext.getEnvironment().getPropertySources()
.addLast(new PropertiesPropertySource("servletConfigYaml", properties));
+ applyLog4jConfiguration(properties, applicationContext.getEnvironment(), servletContext);
}
catch (Exception e) {
servletContext.log("Error loading YAML environment properties from location: " + resource, e);
@@ -128,6 +129,8 @@ else if (properties.containsKey("logging.config")) {
catch (FileNotFoundException e) {
servletContext.log("Error loading log4j config from location: " + log4jConfigLocation, e);
}
+
+ MDC.put("context", servletContext.getContextPath());
}
@@ -16,28 +16,25 @@
package org.cloudfoundry.identity.uaa.oauth;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.TreeSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cloudfoundry.identity.uaa.user.UaaAuthority;
import org.springframework.beans.factory.InitializingBean;
-import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.provider.BaseClientDetails;
import org.springframework.security.oauth2.provider.ClientAlreadyExistsException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientRegistrationService;
/**
* @author Dave Syer
- *
+ *
*/
public class ClientAdminBootstrap implements InitializingBean {
@@ -47,26 +44,13 @@
private ClientRegistrationService clientRegistrationService;
- private Map<String, String> authoritiesToScopes = new HashMap<String, String>();
-
- private Collection<String> validScopes = Arrays.asList("password.write", "openid", "cloud_controller.read",
- "cloud_controller.write", "clients.read", "clients.write", "clients.secret", "tokens.read", "tokens.write",
- "scim.read", "scim.write");
-
private String domain = "cloudfoundry\\.com";
- {
- authoritiesToScopes.put("ROLE_UNTRUSTED", "uaa.none");
- authoritiesToScopes.put("ROLE_RESOURCE", "uaa.resource");
- authoritiesToScopes.put("ROLE_LOGIN", "uaa.login");
- authoritiesToScopes.put("ROLE_ADMIN", "uaa.admin");
- }
-
/**
* The domain suffix (default "cloudfoundry.com") used to detect http redirects. If an http callback in this domain
* is found in a client registration and there is no corresponding value with https as well, then the https value
* will be added.
- *
+ *
* @param domain the domain to set
*/
public void setDomain(String domain) {
@@ -90,7 +74,7 @@ public void setClientRegistrationService(ClientRegistrationService clientRegistr
@Override
public void afterPropertiesSet() throws Exception {
- convertLegacyClients();
+ deleteLegacyClients();
addHttpsCallbacks();
addNewClients();
}
@@ -102,9 +86,6 @@ private void addHttpsCallbacks() {
List<ClientDetails> clients = clientRegistrationService.listClientDetails();
for (ClientDetails client : clients) {
- if (client.getClientId().startsWith("legacy_")) {
- continue;
- }
Set<String> registeredRedirectUri = client.getRegisteredRedirectUri();
if (registeredRedirectUri == null || registeredRedirectUri.isEmpty()) {
continue;
@@ -126,105 +107,21 @@ private void addHttpsCallbacks() {
}
/**
- * Convert legacy clients to best guess for new scopes and authorities.
+ * Delete legacy clients if present.
*/
- private void convertLegacyClients() {
-
+ private void deleteLegacyClients() {
List<ClientDetails> clients = clientRegistrationService.listClientDetails();
for (ClientDetails client : clients) {
if (client.getClientId().startsWith("legacy_")) {
- continue;
- }
- if (!client.getAuthorities().toString().contains("ROLE_")) {
- logger.info("Already converted: " + client);
- continue;
- }
- logger.info("Converting: " + client);
- try {
- BaseClientDetails legacyClient = new BaseClientDetails(client);
- legacyClient.setClientId("legacy_" + client.getClientId());
- if (!clients.contains(legacyClient)) {
- clientRegistrationService.addClientDetails(legacyClient);
+ logger.info("Deleting legacy client " + client.getClientId());
+ try {
+ clientRegistrationService.removeClientDetails(client.getClientId());
+ } catch (Exception e) {
+ logger.error("Failed to remove client.", e);
}
}
- catch (ClientAlreadyExistsException e) {
- // Should not happen
- logger.error("Error creating legacy copy of: " + client);
- }
-
- BaseClientDetails newClient = new BaseClientDetails(client);
- newClient.setResourceIds(Collections.singleton("none"));
- Set<String> userScopes = getUserScopes(client);
- // Use sorted set to make testing easier
- Set<String> clientScopes = new TreeSet<String>(getClientScopes(client));
- if (client.getAuthorizedGrantTypes().equals(Collections.singleton("client_credentials"))) {
- userScopes = Collections.singleton("uaa.none");
- clientScopes.addAll(getUserScopes(client));
- }
- newClient.setScope(userScopes);
- newClient.setAuthorities(AuthorityUtils.createAuthorityList(clientScopes.toArray(new String[clientScopes
- .size()])));
- Integer validity = newClient.getAccessTokenValiditySeconds();
- if (validity != null && validity == 0) {
- newClient.setAccessTokenValiditySeconds(null);
- }
- validity = newClient.getRefreshTokenValiditySeconds();
- if (validity != null && validity == 0) {
- newClient.setRefreshTokenValiditySeconds(null);
- }
- logger.info("Converted: " + newClient);
- clientRegistrationService.updateClientDetails(newClient);
-
- }
-
- }
-
- private Set<String> getUserScopes(ClientDetails client) {
- Set<String> result = new TreeSet<String>();
- Set<String> resourceIds = client.getResourceIds();
- Set<String> scopes = client.getScope();
- for (String scope : scopes) {
- if (scope.equals("openid")) {
- result.add(scope);
- }
- else if (scope.equals("password")) {
- if (resourceIds.contains("password")) {
- result.add("password.write");
- }
- if (resourceIds.contains("clients")) {
- result.add("clients.secret");
- }
- }
- else {
- for (String resource : resourceIds) {
- String value = resource + "." + scope;
- if (validScopes.contains(value)) {
- result.add(value);
- }
- }
- }
- }
- if (result.isEmpty()) {
- // Safety measure, just to prevent errors (empty means all scopes are allowed)
- result.add("uaa.none");
- }
- return result;
- }
-
- private Set<String> getClientScopes(ClientDetails client) {
- Set<String> result = new TreeSet<String>();
- Set<String> authorities = AuthorityUtils.authorityListToSet(client.getAuthorities());
- for (String authority : authorities) {
- if (authoritiesToScopes.containsKey(authority)) {
- result.add(authoritiesToScopes.get(authority));
- }
- }
- if (result.isEmpty()) {
- // Safety measure, just to prevent errors (empty means all scopes are allowed)
- result.add("uaa.none");
}
- return result;
}
private void addNewClients() throws Exception {
@@ -29,21 +29,20 @@
import org.springframework.security.oauth2.common.exceptions.InvalidScopeException;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
-import org.springframework.security.oauth2.provider.AuthorizationRequestFactory;
+import org.springframework.security.oauth2.provider.AuthorizationRequestManager;
import org.springframework.security.oauth2.provider.BaseClientDetails;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.DefaultAuthorizationRequest;
-import org.springframework.security.oauth2.provider.endpoint.ParametersValidator;
/**
- * An {@link AuthorizationRequestFactory} that applies various UAA-specific rules to an authorization request,
+ * An {@link AuthorizationRequestManager} that applies various UAA-specific rules to an authorization request,
* validating it and setting the default values for scopes and resource ids.
*
* @author Dave Syer
*
*/
-public class UaaAuthorizationRequestFactory implements AuthorizationRequestFactory, ParametersValidator {
+public class UaaAuthorizationRequestManager implements AuthorizationRequestManager {
private final ClientDetailsService clientDetailsService;
@@ -55,7 +54,7 @@
private Collection<String> defaultScopes = new HashSet<String>();
- public UaaAuthorizationRequestFactory(ClientDetailsService clientDetailsService) {
+ public UaaAuthorizationRequestManager(ClientDetailsService clientDetailsService) {
this.clientDetailsService = clientDetailsService;
}
@@ -153,6 +152,7 @@ public AuthorizationRequest createAuthorizationRequest(Map<String, String> autho
* @see org.springframework.security.oauth2.provider.endpoint.ParametersValidator#validateParameters(java.util.Map,
* org.springframework.security.oauth2.provider.ClientDetails)
*/
+ @Override
public void validateParameters(Map<String, String> parameters, ClientDetails clientDetails) {
if (parameters.containsKey("scope")) {
Set<String> validScope = clientDetails.getScope();
@@ -174,7 +174,7 @@ public void validateParameters(Map<String, String> parameters, ClientDetails cli
}
}
}
-
+
/**
* Add or remove scopes derived from the current authenticated user's authorities (if any)
*
@@ -43,7 +43,7 @@ public void setUseTokenServices(boolean useTokenServices) {
public void setAutoApproveClients(String[] autoApproveClients) {
this.autoApproveClients = Arrays.asList(autoApproveClients);
}
-
+
/**
* Allows automatic approval for a white list of clients in the implicit grant case.
*
@@ -13,13 +13,7 @@
package org.cloudfoundry.identity.uaa.scim;
import java.security.SecureRandom;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
@@ -67,10 +61,10 @@
* User provisioning and query endpoints. Implements the core API from the Simple Cloud Identity Management (SCIM)
* group. Exposes basic CRUD and query features for user accounts in a backend database. For operations on a single user
* resource supports both "/Users" and "/User" (the latter was from an older version of the specification).
- *
+ *
* @author Luke Taylor
* @author Dave Syer
- *
+ *
* @see <a href="http://www.simplecloud.info">SCIM specs</a>
*/
@Controller
@@ -84,7 +78,7 @@
private ScimGroupMembershipManager membershipManager;
private static final Random passwordGenerator = new SecureRandom();
-
+
private final Map<String, AtomicInteger> errorCounts = new ConcurrentHashMap<String, AtomicInteger>();
private AtomicInteger scimUpdates = new AtomicInteger();
@@ -111,7 +105,7 @@ public void setMessageConverters(HttpMessageConverter<?>[] messageConverters) {
/**
* Map from exception type to Http status.
- *
+ *
* @param statuses the statuses to set
*/
public void setStatuses(Map<Class<? extends Exception>, HttpStatus> statuses) {
@@ -261,14 +255,18 @@ private int getVersion(String userId, String etag) {
@RequestMapping(value = "/Users", method = RequestMethod.GET)
@ResponseBody
- public SearchResults<Map<String, Object>> findUsers(
- @RequestParam(value = "attributes", required = false, defaultValue = "id") String attributesCommaSeparated,
+ public SearchResults<?> findUsers(
+ @RequestParam(value = "attributes", required = false) String attributesCommaSeparated,
@RequestParam(required = false, defaultValue = "id pr") String filter,
@RequestParam(required = false) String sortBy,
@RequestParam(required = false, defaultValue = "ascending") String sortOrder,
@RequestParam(required = false, defaultValue = "1") int startIndex,
@RequestParam(required = false, defaultValue = "100") int count) {
+ if (startIndex<1) {
+ startIndex = 1;
+ }
+
List<ScimUser> input;
try {
input = dao.retrieveUsers(filter, sortBy, sortOrder.equals("ascending"));
@@ -280,6 +278,11 @@ private int getVersion(String userId, String etag) {
throw new ScimException("Invalid filter expression: [" + filter + "]", HttpStatus.BAD_REQUEST);
}
+ if (!StringUtils.hasLength(attributesCommaSeparated)) {
+ // Return all user data
+ return new SearchResults<ScimUser>(SearchResultsFactory.schemas, input, startIndex, count, input.size());
+ }
+
AttributeNameMapper mapper = new SimpleAttributeNameMapper(Collections.<String, String> singletonMap("emails\\.(.*)", "emails.![$1]"));
String[] attributes = attributesCommaSeparated.split(",");
try {
@@ -7,7 +7,7 @@
import java.util.*;
public class SearchResultsFactory {
- private static final Collection<String> schemas = Arrays.asList(ScimUser.SCHEMAS);
+ static final Collection<String> schemas = Arrays.asList(ScimUser.SCHEMAS);
public static <T> SearchResults<Map<String, Object>> buildSearchResultFrom (List<T> input, int startIndex, int count, String[] attributes) {
return buildSearchResultFrom(input, startIndex, count, attributes, new SimpleAttributeNameMapper(Collections.<String, String> emptyMap()));
@@ -86,7 +86,7 @@ public void setEnabled(boolean enabled) {
@RequestMapping(value = "/ids/Users", method = RequestMethod.GET)
@ResponseBody
- public SearchResults<Map<String, Object>> findUsers(
+ public SearchResults<?> findUsers(
@RequestParam(required = true, defaultValue = "") String filter,
@RequestParam(required = false, defaultValue = "ascending") String sortOrder,
@RequestParam(required = false, defaultValue = "1") int startIndex,
Oops, something went wrong.

0 comments on commit d6a8f87

Please sign in to comment.