package org.apereo.cas.services; import com.google.common.base.Throwables; import org.apache.commons.io.FileUtils; import org.apereo.cas.authentication.principal.ShibbolethCompatiblePersistentIdGenerator; import org.apereo.cas.services.support.RegisteredServiceRegexAttributeFilter; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.springframework.core.io.ClassPathResource; import java.net.URI; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; 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.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; import static org.junit.Assert.*; /** * This is {@link AbstractResourceBasedServiceRegistryDaoTests}. * * @author Misagh Moayyed * @since 5.0.0 */ public abstract class AbstractResourceBasedServiceRegistryDaoTests { public static final ClassPathResource RESOURCE = new ClassPathResource("services"); private static final String SERVICE_ID = "testId"; private static final String THEME = "theme"; private static final String DESCRIPTION = "description"; private static final String HTTPS_SERVICE_ID = "^https://.+"; @Rule public ExpectedException thrown = ExpectedException.none(); protected ServiceRegistryDao dao; @BeforeClass public static void prepTests() throws Exception { FileUtils.cleanDirectory(RESOURCE.getFile()); } @Test public void checkLoadingOfServiceFiles() throws Exception { prepTests(); verifySaveAttributeReleasePolicyMappingRules(); verifySaveAttributeReleasePolicyAllowedAttrRulesAndFilter(); assertEquals(this.dao.load().size(), 2); } @Test public void checkSaveMethodWithNonExistentServiceAndNoAttributes() { final RegexRegisteredService r = new RegexRegisteredService(); r.setName("testSaveMethodWithNonExistentServiceAndNoAttributes"); r.setServiceId(SERVICE_ID); r.setTheme(THEME); r.setDescription(DESCRIPTION); final RegisteredService r2 = this.dao.save(r); final RegisteredService r3 = this.dao.findServiceById(r2.getId()); assertEquals(r, r2); assertEquals(r2, r3); } @Test public void execSaveWithAuthnMethodPolicy() { final RegexRegisteredService r = new RegexRegisteredService(); r.setName("execSaveWithAuthnMethodPolicy"); r.setServiceId(SERVICE_ID); r.setTheme(THEME); r.setDescription(DESCRIPTION); final DefaultRegisteredServiceMultifactorPolicy policy = new DefaultRegisteredServiceMultifactorPolicy(); policy.setFailureMode(RegisteredServiceMultifactorPolicy.FailureModes.PHANTOM); final Set<String> set = new HashSet<>(); set.add("duoAuthenticationProvider"); policy.setMultifactorAuthenticationProviders(set); policy.setPrincipalAttributeNameTrigger("memberOf"); policy.setPrincipalAttributeValueToMatch("cas|CAS|admin"); r.setMultifactorPolicy(policy); final RegisteredService r2 = this.dao.save(r); assertEquals(r2, r); } @Test public void execSaveMethodWithDefaultUsernameAttribute() { final RegexRegisteredService r = new RegexRegisteredService(); r.setName("testSaveMethodWithDefaultUsernameAttribute"); r.setServiceId(SERVICE_ID); r.setTheme(THEME); r.setDescription(DESCRIPTION); r.setUsernameAttributeProvider(new DefaultRegisteredServiceUsernameProvider()); final RegisteredService r2 = this.dao.save(r); assertEquals(r2, r); } @Test public void ensureSaveMethodWithDefaultPrincipalAttribute() { final RegexRegisteredService r = new RegexRegisteredService(); r.setName("testSaveMethodWithDefaultPrincipalAttribute"); r.setServiceId(SERVICE_ID); r.setTheme(THEME); r.setDescription(DESCRIPTION); r.setUsernameAttributeProvider(new PrincipalAttributeRegisteredServiceUsernameProvider("cn", "UPPER")); final RegisteredService r2 = this.dao.save(r); assertEquals(r2, r); } @Test public void verifySaveMethodWithDefaultAnonymousAttribute() { final RegexRegisteredService r = new RegexRegisteredService(); r.setName("testSaveMethodWithDefaultAnonymousAttribute"); r.setServiceId(SERVICE_ID); r.setTheme(THEME); r.setDescription(DESCRIPTION); r.setUsernameAttributeProvider(new AnonymousRegisteredServiceUsernameAttributeProvider( new ShibbolethCompatiblePersistentIdGenerator("helloworld") )); final RegisteredService r2 = this.dao.save(r); this.dao.load(); final RegisteredService r3 = this.dao.findServiceById(r2.getId()); final AnonymousRegisteredServiceUsernameAttributeProvider anon = (AnonymousRegisteredServiceUsernameAttributeProvider) r3.getUsernameAttributeProvider(); final ShibbolethCompatiblePersistentIdGenerator ss = (ShibbolethCompatiblePersistentIdGenerator) anon.getPersistentIdGenerator(); assertEquals(new String(ss.getSalt()), "helloworld"); assertEquals(r2, r3); } @Test public void verifySaveAttributeReleasePolicy() { final RegexRegisteredService r = new RegexRegisteredService(); r.setName("testSaveAttributeReleasePolicy"); r.setServiceId(SERVICE_ID); r.setTheme(THEME); r.setDescription(DESCRIPTION); r.setAttributeReleasePolicy(new ReturnAllAttributeReleasePolicy()); final RegisteredService r2 = this.dao.save(r); final RegisteredService r3 = this.dao.findServiceById(r2.getId()); assertEquals(r, r2); assertEquals(r2, r3); assertNotNull(r3.getAttributeReleasePolicy()); assertEquals(r2.getAttributeReleasePolicy(), r3.getAttributeReleasePolicy()); } @Test public void verifySaveMethodWithExistingServiceNoAttribute() { final RegexRegisteredService r = new RegexRegisteredService(); r.setName("testSaveMethodWithExistingServiceNoAttribute"); r.setServiceId(SERVICE_ID); r.setTheme(THEME); r.setDescription(DESCRIPTION); this.dao.save(r); r.setTheme("mytheme"); this.dao.save(r); final RegisteredService r3 = this.dao.findServiceById(r.getId()); assertEquals(r, r3); } @Test public void verifySaveAttributeReleasePolicyMappingRules() { final RegexRegisteredService r = new RegexRegisteredService(); r.setName("testSaveAttributeReleasePolicyMappingRules"); r.setServiceId(SERVICE_ID); final Map<String, String> map = new HashMap<>(); map.put("attr1", "newattr1"); map.put("attr2", "newattr2"); map.put("attr2", "newattr3"); final ReturnMappedAttributeReleasePolicy policy = new ReturnMappedAttributeReleasePolicy(); policy.setAllowedAttributes(map); r.setAttributeReleasePolicy(policy); final RegisteredService r2 = this.dao.save(r); final RegisteredService r3 = this.dao.findServiceById(r2.getId()); assertEquals(r, r2); assertEquals(r2, r3); assertNotNull(r3.getAttributeReleasePolicy()); assertEquals(r2.getAttributeReleasePolicy(), r3.getAttributeReleasePolicy()); } @Test public void verifySaveAttributeReleasePolicyAllowedAttrRules() { final RegexRegisteredService r = new RegexRegisteredService(); r.setName("testSaveAttributeReleasePolicyAllowedAttrRules"); r.setServiceId(SERVICE_ID); final ReturnAllowedAttributeReleasePolicy policy = new ReturnAllowedAttributeReleasePolicy(); policy.setAllowedAttributes(Arrays.asList("1", "2", "3")); r.setAttributeReleasePolicy(policy); final RegisteredService r2 = this.dao.save(r); final RegisteredService r3 = this.dao.findServiceById(r2.getId()); assertEquals(r, r2); assertEquals(r2, r3); assertNotNull(r3.getAttributeReleasePolicy()); assertEquals(r2.getAttributeReleasePolicy(), r3.getAttributeReleasePolicy()); } @Test public void verifySaveAttributeReleasePolicyAllowedAttrRulesAndFilter() { final RegexRegisteredService r = new RegexRegisteredService(); r.setName("testSaveAttributeReleasePolicyAllowedAttrRulesAndFilter"); r.setServiceId(SERVICE_ID); r.setTheme("testtheme"); r.setEvaluationOrder(1000); r.setAccessStrategy(new DefaultRegisteredServiceAccessStrategy(true, false)); r.setProxyPolicy(new RegexMatchingRegisteredServiceProxyPolicy("https://.+")); r.setRequiredHandlers(Stream.of("h1", "h2").collect(Collectors.toSet())); final ReturnAllowedAttributeReleasePolicy policy = new ReturnAllowedAttributeReleasePolicy(); policy.setAllowedAttributes(Arrays.asList("1", "2", "3")); r.setAttributeReleasePolicy(policy); r.getAttributeReleasePolicy().setAttributeFilter(new RegisteredServiceRegexAttributeFilter("\\w+")); final RegisteredService r2 = this.dao.save(r); final RegisteredService r3 = this.dao.findServiceById(r2.getId()); assertEquals(r, r2); assertEquals(r2, r3); assertNotNull(r3.getAttributeReleasePolicy()); assertEquals(r2.getAttributeReleasePolicy(), r3.getAttributeReleasePolicy()); } @Test public void verifyServiceType() { final RegexRegisteredService r = new RegexRegisteredService(); r.setServiceId(HTTPS_SERVICE_ID); r.setName("testServiceType"); r.setTheme("testtheme"); r.setEvaluationOrder(1000); final RegisteredService r2 = this.dao.save(r); assertTrue(r2 instanceof RegexRegisteredService); } @Test public void verifyServiceWithInvalidFileName() { final RegexRegisteredService r = new RegexRegisteredService(); r.setServiceId(HTTPS_SERVICE_ID); r.setName("hell/o@world:*"); r.setEvaluationOrder(1000); this.thrown.expect(IllegalArgumentException.class); this.dao.save(r); } @Test public void verifyServiceRemovals() throws Exception { final List<RegisteredService> list = new ArrayList<>(5); IntStream.range(1, 5).forEach(i -> { final RegexRegisteredService r = new RegexRegisteredService(); r.setServiceId(HTTPS_SERVICE_ID); r.setName("testServiceType"); r.setTheme("testtheme"); r.setEvaluationOrder(1000); r.setId(i * 100); list.add(this.dao.save(r)); }); list.forEach(r2 -> { try { Thread.sleep(500); this.dao.delete(r2); Thread.sleep(2000); } catch (final InterruptedException e) { throw Throwables.propagate(e); } assertNull(this.dao.findServiceById(r2.getId())); }); } @Test public void checkForAuthorizationStrategy() { final RegexRegisteredService r = new RegexRegisteredService(); r.setServiceId(HTTPS_SERVICE_ID); r.setName("checkForAuthorizationStrategy"); r.setId(42); final DefaultRegisteredServiceAccessStrategy authz = new DefaultRegisteredServiceAccessStrategy(false, false); final Map<String, Set<String>> attrs = new HashMap<>(); attrs.put("cn", Collections.singleton("v1, v2, v3")); attrs.put("memberOf", Collections.singleton("v4, v5, v6")); authz.setRequiredAttributes(attrs); r.setAccessStrategy(authz); final RegisteredService r2 = this.dao.save(r); final RegisteredService r3 = this.dao.findServiceById(r2.getId()); assertEquals(r2, r3); } @Test public void verifyAccessStrategyWithStarEndDate() throws Exception { final RegexRegisteredService r = new RegexRegisteredService(); r.setServiceId(HTTPS_SERVICE_ID); r.setName("verifyAAccessStrategyWithStarEndDate"); r.setId(62); final TimeBasedRegisteredServiceAccessStrategy authz = new TimeBasedRegisteredServiceAccessStrategy(true, false); authz.setStartingDateTime(ZonedDateTime.now(ZoneOffset.UTC).plusDays(1).toString()); authz.setEndingDateTime(ZonedDateTime.now(ZoneOffset.UTC).plusDays(10).toString()); authz.setUnauthorizedRedirectUrl(new URI("https://www.github.com")); r.setAccessStrategy(authz); final RegisteredService r2 = this.dao.save(r); final RegisteredService r3 = this.dao.findServiceById(r2.getId()); assertEquals(r2, r3); } @Test public void verifyAccessStrategyWithEndpoint() throws Exception { final RegexRegisteredService r = new RegexRegisteredService(); r.setServiceId(HTTPS_SERVICE_ID); r.setName("verifyAccessStrategyWithEndpoint"); r.setId(62); final RemoteEndpointServiceAccessStrategy authz = new RemoteEndpointServiceAccessStrategy(); authz.setEndpointUrl("http://www.google.com?this=that"); authz.setAcceptableResponseCodes("200,405,403"); authz.setUnauthorizedRedirectUrl(new URI("https://www.github.com")); r.setAccessStrategy(authz); final RegisteredService r2 = this.dao.save(r); final RegisteredService r3 = this.dao.findServiceById(r2.getId()); assertEquals(r2, r3); } @Test public void serializePublicKeyForServiceAndVerify() throws Exception { final RegisteredServicePublicKey publicKey = new RegisteredServicePublicKeyImpl( "classpath:RSA1024Public.key", "RSA"); final RegexRegisteredService r = new RegexRegisteredService(); r.setServiceId(HTTPS_SERVICE_ID); r.setName("serializePublicKeyForServiceAndVerify"); r.setId(4245); r.setPublicKey(publicKey); this.dao.save(r); this.dao.load(); assertNotNull(this.dao.findServiceById(r.getId())); } @Test public void checkNullabilityOfAccessStrategy() { final RegexRegisteredService r = new RegexRegisteredService(); r.setServiceId(HTTPS_SERVICE_ID); r.setName("checkNullabilityOfAccessStrategy"); r.setId(43210); r.setAccessStrategy(null); this.dao.save(r); this.dao.load(); final RegisteredService s = this.dao.findServiceById(43210); assertNotNull(s); assertNotNull(s.getAccessStrategy()); } @Test public void persistCustomServiceProperties() throws Exception { final RegexRegisteredService r = new RegexRegisteredService(); r.setServiceId(HTTPS_SERVICE_ID); r.setName("persistCustomServiceProperties"); r.setId(4245); final Map<String, RegisteredServiceProperty> properties = new HashMap<>(); final DefaultRegisteredServiceProperty property = new DefaultRegisteredServiceProperty(); final Set<String> values = new HashSet<>(); values.add("value1"); values.add("value2"); property.setValues(values); properties.put("field1", property); final DefaultRegisteredServiceProperty property2 = new DefaultRegisteredServiceProperty(); final Set<String> values2 = new HashSet<>(); values2.add("value12"); values2.add("value22"); property2.setValues(values2); properties.put("field2", property2); r.setProperties(properties); this.dao.save(r); this.dao.load(); assertNotNull(this.dao.findServiceById(r.getId())); assertEquals(r.getProperties().size(), 2); assertNotNull(r.getProperties().get("field1")); final RegisteredServiceProperty prop = r.getProperties().get("field1"); assertEquals(prop.getValues().size(), 2); } }