View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.fit.core;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertNull;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  import static org.junit.jupiter.api.Assertions.fail;
26  import static org.junit.jupiter.api.Assumptions.assumeTrue;
27  
28  import java.security.AccessControlException;
29  import java.util.List;
30  import java.util.Locale;
31  import javax.ws.rs.core.GenericType;
32  import javax.ws.rs.core.Response;
33  import org.apache.commons.lang3.StringUtils;
34  import org.apache.syncope.client.lib.SyncopeClient;
35  import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
36  import org.apache.syncope.common.keymaster.client.api.model.Domain;
37  import org.apache.syncope.common.lib.SyncopeConstants;
38  import org.apache.syncope.common.lib.request.UserCR;
39  import org.apache.syncope.common.lib.to.ConnInstanceTO;
40  import org.apache.syncope.common.lib.to.ExecTO;
41  import org.apache.syncope.common.lib.to.Item;
42  import org.apache.syncope.common.lib.to.Mapping;
43  import org.apache.syncope.common.lib.to.PagedResult;
44  import org.apache.syncope.common.lib.to.Provision;
45  import org.apache.syncope.common.lib.to.ProvisioningResult;
46  import org.apache.syncope.common.lib.to.PullTaskTO;
47  import org.apache.syncope.common.lib.to.PushTaskTO;
48  import org.apache.syncope.common.lib.to.RealmTO;
49  import org.apache.syncope.common.lib.to.ResourceTO;
50  import org.apache.syncope.common.lib.to.UserTO;
51  import org.apache.syncope.common.lib.types.AnyTypeKind;
52  import org.apache.syncope.common.lib.types.ExecStatus;
53  import org.apache.syncope.common.lib.types.MappingPurpose;
54  import org.apache.syncope.common.lib.types.MatchingRule;
55  import org.apache.syncope.common.lib.types.PullMode;
56  import org.apache.syncope.common.lib.types.SchemaType;
57  import org.apache.syncope.common.lib.types.TaskType;
58  import org.apache.syncope.common.rest.api.beans.AnyQuery;
59  import org.apache.syncope.common.rest.api.beans.RealmQuery;
60  import org.apache.syncope.common.rest.api.beans.ReconQuery;
61  import org.apache.syncope.common.rest.api.beans.SchemaQuery;
62  import org.apache.syncope.common.rest.api.beans.TaskQuery;
63  import org.apache.syncope.common.rest.api.service.ConnectorService;
64  import org.apache.syncope.common.rest.api.service.RealmService;
65  import org.apache.syncope.common.rest.api.service.ReconciliationService;
66  import org.apache.syncope.common.rest.api.service.ResourceService;
67  import org.apache.syncope.common.rest.api.service.SchemaService;
68  import org.apache.syncope.common.rest.api.service.TaskService;
69  import org.apache.syncope.common.rest.api.service.UserSelfService;
70  import org.apache.syncope.common.rest.api.service.UserService;
71  import org.apache.syncope.fit.AbstractITCase;
72  import org.identityconnectors.framework.common.objects.ObjectClass;
73  import org.junit.jupiter.api.BeforeEach;
74  import org.junit.jupiter.api.Test;
75  
76  public class MultitenancyITCase extends AbstractITCase {
77  
78      @BeforeEach
79      public void multitenancyCheck() {
80          List<Domain> initial = domainOps.list();
81          assertNotNull(initial);
82          assumeTrue(initial.stream().anyMatch(domain -> "Two".equals(domain.getKey())));
83  
84          CLIENT_FACTORY = new SyncopeClientFactoryBean().setAddress(ADDRESS).setDomain("Two");
85  
86          String envContentType = System.getProperty(ENV_KEY_CONTENT_TYPE);
87          if (StringUtils.isNotBlank(envContentType)) {
88              CLIENT_FACTORY.setContentType(envContentType);
89          }
90          LOG.info("Performing IT with content type {}", CLIENT_FACTORY.getContentType().getMediaType());
91  
92          ADMIN_CLIENT = CLIENT_FACTORY.create(ADMIN_UNAME, "password2");
93      }
94  
95      @Test
96      public void readPlainSchemas() {
97          assertEquals(1, ADMIN_CLIENT.getService(SchemaService.class).
98                  search(new SchemaQuery.Builder().type(SchemaType.PLAIN).build()).size());
99      }
100 
101     @Test
102     public void readRealm() {
103         PagedResult<RealmTO> realms = ADMIN_CLIENT.getService(RealmService.class).
104                 search(new RealmQuery.Builder().keyword("*").build());
105         assertEquals(1, realms.getTotalCount());
106         assertEquals(1, realms.getResult().size());
107         assertEquals(SyncopeConstants.ROOT_REALM, realms.getResult().get(0).getName());
108     }
109 
110     @Test
111     public void createUser() {
112         assertNull(ADMIN_CLIENT.getService(RealmService.class).
113                 search(new RealmQuery.Builder().keyword("*").build()).getResult().get(0).getPasswordPolicy());
114 
115         UserCR userCR = new UserCR();
116         userCR.setRealm(SyncopeConstants.ROOT_REALM);
117         userCR.setUsername(getUUIDString());
118         userCR.setPassword("password");
119 
120         Response response = ADMIN_CLIENT.getService(UserService.class).create(userCR);
121         assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
122 
123         UserTO user = response.readEntity(new GenericType<ProvisioningResult<UserTO>>() {
124         }).getEntity();
125         assertNotNull(user);
126     }
127 
128     @Test
129     public void createResourceAndPull() {
130         // read connector
131         ConnInstanceTO conn = ADMIN_CLIENT.getService(ConnectorService.class).
132                 read("b7ea96c3-c633-488b-98a0-b52ac35850f7", Locale.ENGLISH.getLanguage());
133         assertNotNull(conn);
134         assertEquals("LDAP", conn.getDisplayName());
135 
136         // prepare resource
137         ResourceTO resource = new ResourceTO();
138         resource.setKey("new-ldap-resource");
139         resource.setConnector(conn.getKey());
140 
141         try {
142             Provision provisionTO = new Provision();
143             provisionTO.setAnyType(AnyTypeKind.USER.name());
144             provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
145             resource.getProvisions().add(provisionTO);
146 
147             Mapping mapping = new Mapping();
148             mapping.setConnObjectLink("'uid=' + username + ',ou=people,o=isp'");
149             provisionTO.setMapping(mapping);
150 
151             Item item = new Item();
152             item.setIntAttrName("username");
153             item.setExtAttrName("cn");
154             item.setPurpose(MappingPurpose.BOTH);
155             mapping.setConnObjectKeyItem(item);
156 
157             item = new Item();
158             item.setPassword(true);
159             item.setIntAttrName("password");
160             item.setExtAttrName("userPassword");
161             item.setPurpose(MappingPurpose.BOTH);
162             item.setMandatoryCondition("true");
163             mapping.add(item);
164 
165             item = new Item();
166             item.setIntAttrName("key");
167             item.setPurpose(MappingPurpose.BOTH);
168             item.setExtAttrName("sn");
169             item.setMandatoryCondition("true");
170             mapping.add(item);
171 
172             item = new Item();
173             item.setIntAttrName("email");
174             item.setPurpose(MappingPurpose.BOTH);
175             item.setExtAttrName("mail");
176             mapping.add(item);
177 
178             // create resource
179             Response response = ADMIN_CLIENT.getService(ResourceService.class).create(resource);
180             assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
181             resource = ADMIN_CLIENT.getService(ResourceService.class).read(resource.getKey());
182             assertNotNull(resource);
183 
184             // create pull task
185             PullTaskTO task = new PullTaskTO();
186             task.setName("LDAP Pull Task");
187             task.setActive(true);
188             task.setDestinationRealm(SyncopeConstants.ROOT_REALM);
189             task.setResource(resource.getKey());
190             task.setPullMode(PullMode.FULL_RECONCILIATION);
191             task.setPerformCreate(true);
192 
193             response = ADMIN_CLIENT.getService(TaskService.class).create(TaskType.PULL, task);
194             assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
195             task = ADMIN_CLIENT.getService(TaskService.class).read(TaskType.PULL,
196                     StringUtils.substringAfterLast(response.getLocation().toASCIIString(), "/"), true);
197             assertNotNull(resource);
198 
199             // pull
200             ExecTO execution = AbstractTaskITCase.execProvisioningTask(
201                     ADMIN_CLIENT.getService(TaskService.class), TaskType.PULL, task.getKey(), MAX_WAIT_SECONDS, false);
202 
203             // verify execution status
204             String status = execution.getStatus();
205             assertNotNull(status);
206             assertEquals(ExecStatus.SUCCESS, ExecStatus.valueOf(status));
207 
208             // verify that pulled user is found
209             if (IS_EXT_SEARCH_ENABLED) {
210                 try {
211                     Thread.sleep(2000);
212                 } catch (InterruptedException ex) {
213                     // ignore
214                 }
215             }
216             PagedResult<UserTO> matchingUsers = ADMIN_CLIENT.getService(UserService.class).
217                     search(new AnyQuery.Builder().
218                             realm(SyncopeConstants.ROOT_REALM).
219                             fiql(SyncopeClient.getUserSearchConditionBuilder().
220                                     is("username").equalTo("pullFromLDAP").query()).
221                             build());
222             assertNotNull(matchingUsers);
223             assertEquals(1, matchingUsers.getResult().size());
224 
225             // SYNCOPE-1374
226             String pullFromLDAPKey = matchingUsers.getResult().get(0).getKey();
227 
228             assertEquals(0, ADMIN_CLIENT.getService(TaskService.class).
229                     search(new TaskQuery.Builder(TaskType.PROPAGATION).
230                             anyTypeKind(AnyTypeKind.USER).entityKey(pullFromLDAPKey).build()).getSize());
231 
232             PushTaskTO pushTask = new PushTaskTO();
233             pushTask.setPerformUpdate(true);
234             pushTask.setMatchingRule(MatchingRule.UPDATE);
235             ADMIN_CLIENT.getService(ReconciliationService.class).
236                     push(new ReconQuery.Builder(AnyTypeKind.USER.name(), resource.getKey()).
237                             anyKey(pullFromLDAPKey).build(), pushTask);
238 
239             assertEquals(1, ADMIN_CLIENT.getService(TaskService.class).
240                     search(new TaskQuery.Builder(TaskType.PROPAGATION).
241                             anyTypeKind(AnyTypeKind.USER).entityKey(pullFromLDAPKey).build()).getSize());
242         } finally {
243             ADMIN_CLIENT.getService(ResourceService.class).delete(resource.getKey());
244         }
245     }
246 
247     @Test
248     public void issueSYNCOPE1377() {
249         try {
250             new SyncopeClientFactoryBean().setAddress(ADDRESS).setDomain("NotExisting").
251                     create(ADMIN_UNAME, ADMIN_PWD).
252                     getService(UserSelfService.class).
253                     create(UserITCase.getUniqueSample("syncope1377@syncope.apache.org"));
254             fail("This should not happen");
255         } catch (AccessControlException e) {
256             assertTrue(e.getMessage().contains("Could not find domain NotExisting"));
257         }
258     }
259 }