@Override protected void securityChecks(final User user) { // Allows anonymous (during self-registration) and self (during self-update) to read own user, // otherwise goes through security checks to see if required entitlements are owned if (!AuthContextUtils.getUsername().equals(anonymousUser) && !AuthContextUtils.getUsername().equals(user.getUsername())) { Set<String> authRealms = AuthContextUtils.getAuthorizations().get(StandardEntitlement.USER_READ); boolean authorized = IterableUtils.matchesAny( authRealms, new Predicate<String>() { @Override public boolean evaluate(final String realm) { return user.getRealm().getFullPath().startsWith(realm); } }); if (authRealms == null || authRealms.isEmpty() || !authorized) { throw new DelegatedAdministrationException(AnyTypeKind.USER, user.getKey()); } } }
@Transactional(readOnly = true) @Override public Pair<Boolean, Boolean> enforcePolicies(final User user) { // ------------------------------ // Verify password policies // ------------------------------ LOG.debug("Password Policy enforcement"); try { int maxPPSpecHistory = 0; for (PasswordPolicy policy : getPasswordPolicies(user)) { if (user.getPassword() == null && !policy.isAllowNullPassword()) { throw new PasswordPolicyException("Password mandatory"); } for (PasswordRuleConf ruleConf : policy.getRuleConfs()) { Class<? extends PasswordRule> ruleClass = implementationLookup.getPasswordRuleClass(ruleConf.getClass()); if (ruleClass == null) { LOG.warn("Could not find matching password rule for {}", ruleConf.getClass()); } else { // fetch (or create) rule PasswordRule rule; if (ApplicationContextProvider.getBeanFactory() .containsSingleton(ruleClass.getName())) { rule = (PasswordRule) ApplicationContextProvider.getBeanFactory().getSingleton(ruleClass.getName()); } else { rule = (PasswordRule) ApplicationContextProvider.getBeanFactory() .createBean(ruleClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false); ApplicationContextProvider.getBeanFactory() .registerSingleton(ruleClass.getName(), rule); } // enforce rule rule.enforce(ruleConf, user); } } if (user.verifyPasswordHistory(user.getClearPassword(), policy.getHistoryLength())) { throw new PasswordPolicyException("Password value was used in the past: not allowed"); } if (policy.getHistoryLength() > maxPPSpecHistory) { maxPPSpecHistory = policy.getHistoryLength(); } } // update user's password history with encrypted password if (maxPPSpecHistory > 0 && user.getPassword() != null) { user.getPasswordHistory().add(user.getPassword()); } // keep only the last maxPPSpecHistory items in user's password history if (maxPPSpecHistory < user.getPasswordHistory().size()) { for (int i = 0; i < user.getPasswordHistory().size() - maxPPSpecHistory; i++) { user.getPasswordHistory().remove(i); } } } catch (Exception e) { LOG.error("Invalid password for {}", user, e); throw new InvalidEntityException( User.class, EntityViolationType.InvalidPassword, e.getMessage()); } finally { // password has been validated, let's remove its clear version user.removeClearPassword(); } // ------------------------------ // Verify account policies // ------------------------------ LOG.debug("Account Policy enforcement"); boolean suspend = false; boolean propagateSuspension = false; try { if (adminUser.equals(user.getUsername()) || anonymousUser.equals(user.getUsername())) { throw new AccountPolicyException("Not allowed: " + user.getUsername()); } for (AccountPolicy policy : getAccountPolicies(user)) { for (AccountRuleConf ruleConf : policy.getRuleConfs()) { Class<? extends AccountRule> ruleClass = implementationLookup.getAccountRuleClass(ruleConf.getClass()); if (ruleClass == null) { LOG.warn("Could not find matching password rule for {}", ruleConf.getClass()); } else { // fetch (or create) rule AccountRule rule; if (ApplicationContextProvider.getBeanFactory() .containsSingleton(ruleClass.getName())) { rule = (AccountRule) ApplicationContextProvider.getBeanFactory().getSingleton(ruleClass.getName()); } else { rule = (AccountRule) ApplicationContextProvider.getBeanFactory() .createBean(ruleClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false); ApplicationContextProvider.getBeanFactory() .registerSingleton(ruleClass.getName(), rule); } // enforce rule rule.enforce(ruleConf, user); } } suspend |= user.getFailedLogins() != null && policy.getMaxAuthenticationAttempts() > 0 && user.getFailedLogins() > policy.getMaxAuthenticationAttempts() && !user.isSuspended(); propagateSuspension |= policy.isPropagateSuspension(); } } catch (Exception e) { LOG.error("Invalid username for {}", user, e); throw new InvalidEntityException( User.class, EntityViolationType.InvalidUsername, e.getMessage()); } return ImmutablePair.of(suspend, propagateSuspension); }