8e05b8d16a40d98d0cd366b01b3569e5147a8e83
[java-idp.git] / tests / edu / internet2 / middleware / shibboleth / aa / attrresolv / ResolverTests.java
1 /*
2  * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package edu.internet2.middleware.shibboleth.aa.attrresolv;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.net.MalformedURLException;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Iterator;
25
26 import junit.framework.TestCase;
27
28 import org.apache.log4j.BasicConfigurator;
29 import org.apache.log4j.Level;
30 import org.apache.log4j.Logger;
31 import org.opensaml.SAMLException;
32
33 import edu.internet2.middleware.shibboleth.aa.AAAttribute;
34 import edu.internet2.middleware.shibboleth.aa.AAAttributeSet;
35 import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolverAttributeSet.ResolverAttributeIterator;
36 import edu.internet2.middleware.shibboleth.aa.attrresolv.provider.ScopedStringValueHandler;
37 import edu.internet2.middleware.shibboleth.common.LocalPrincipal;
38
39 /**
40  * Validation suite for the <code>AttributeResolver</code>.
41  * 
42  * @author Walter Hoehn(wassa@columbia.edu)
43  * @author Vishal Goenka
44  */
45
46 public class ResolverTests extends TestCase {
47
48         private static Logger log = Logger.getLogger(ResolverTests.class.getName());
49         // Simple explanatory booleans, which are helpful when passed in functions as compared to true/false
50         private static final boolean DO_SORT = true;
51         private static final boolean DO_NOT_SORT = false;
52
53         public ResolverTests(String name) {
54
55                 super(name);
56                 BasicConfigurator.resetConfiguration();
57                 BasicConfigurator.configure();
58                 Logger.getRootLogger().setLevel(Level.OFF);
59         }
60
61         public static void main(String[] args) {
62
63                 junit.textui.TestRunner.run(ResolverTests.class);
64                 BasicConfigurator.configure();
65                 Logger.getRootLogger().setLevel(Level.OFF);
66         }
67
68         /**
69          * @see junit.framework.TestCase#setUp()
70          */
71         protected void setUp() throws Exception {
72
73                 super.setUp();
74         }
75
76         public void testBasic() {
77
78                 try {
79                         File file = new File("data/resolver1.xml");
80                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
81
82                         AAAttributeSet inputAttributes = new AAAttributeSet(new AAAttribute[]{
83                                         new AAAttribute("urn:mace:dir:attribute-def:eduPersonNickName"),
84                                         new AAAttribute("urn:mace:dir:attribute-def:eduPersonEntitlement")});
85
86                         AAAttributeSet outputAttributes = new AAAttributeSet(new AAAttribute[]{new AAAttribute(
87                                         "urn:mace:dir:attribute-def:eduPersonEntitlement",
88                                         new Object[]{"urn:mace:example.edu:exampleEntitlement"})});
89
90                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
91
92                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
93
94                 } catch (AttributeResolverException e) {
95                         fail("Couldn't load attribute resolver: " + e.getMessage());
96                 } catch (MalformedURLException e) {
97                         fail("Error in test specification: " + e.getMessage());
98                 } catch (SAMLException e) {
99                         fail("Error creating SAML Attribute: " + e.getMessage());
100                 }
101         }
102
103         public void testSmartScoping() {
104
105                 try {
106
107                         File file = new File("data/resolver2.xml");
108                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
109
110                         AAAttributeSet inputAttributes = new AAAttributeSet(new AAAttribute[]{
111                                         new AAAttribute("urn:mace:dir:attribute-def:eduPersonPrincipalName"), new AAAttribute("foo")});
112
113                         AAAttributeSet outputAttributes = new AAAttributeSet(
114                                         new AAAttribute[]{
115                                                         // Attribute should have scope appended to connector output
116                                                         new AAAttribute("urn:mace:dir:attribute-def:eduPersonPrincipalName",
117                                                                         new Object[]{"mytestuser@example.edu"}, new ScopedStringValueHandler("example.edu")),
118                                                         // Attribute should retain scope from connector output
119                                                         new AAAttribute("foo", new Object[]{"bar@example.com"}, new ScopedStringValueHandler(
120                                                                         "example.edu"))});
121
122                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
123                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
124
125                 } catch (AttributeResolverException e) {
126                         fail("Couldn't load attribute resolver: " + e.getMessage());
127                 } catch (MalformedURLException e) {
128                         fail("Error in test specification: " + e.getMessage());
129                 } catch (SAMLException e) {
130                         fail("Error creating SAML Attribute: " + e.getMessage());
131                 }
132         }
133
134         public void testExceptionForNoPlugIns() {
135
136                 try {
137                         File file = new File("data/resolver3.xml");
138                         new AttributeResolver(file.toURL().toString());
139
140                         fail("Attribute Resolver loaded even when no PlugIns were configured.");
141                 } catch (AttributeResolverException e) {
142                         // This exception should be thrown, ignoring
143                 } catch (MalformedURLException e) {
144                         fail("Error in test specification: " + e.getMessage());
145                 }
146         }
147
148         public void testExceptionForNoValidPlugIns() {
149
150                 try {
151                         File file = new File("data/resolver4.xml");
152                         new AttributeResolver(file.toURL().toString());
153                         fail("Attribute Resolver loaded even when no PlugIns were successfully registered.");
154                 } catch (AttributeResolverException e) {
155                         // This exception should be thrown, ignoring
156                 } catch (MalformedURLException e) {
157                         fail("Error in test specification: " + e.getMessage());
158                 }
159         }
160
161         public void testFailToLoadCircularDependencies() {
162
163                 try {
164                         File file = new File("data/resolver5.xml");
165                         new AttributeResolver(file.toURL().toString());
166                         fail("Attribute Resolver loaded even when no only PlugIns with circular dependencies were configured.");
167                 } catch (AttributeResolverException e) {
168                         // This exception should be thrown, ignoring
169                 } catch (MalformedURLException e) {
170                         fail("Error in test specification: " + e.getMessage());
171                 }
172         }
173
174         public void testFailToLoadCircularDependenciesDeeper() {
175
176                 try {
177                         File file = new File("data/resolver6.xml");
178                         new AttributeResolver(file.toURL().toString());
179                         fail("Attribute Resolver loaded even when no only PlugIns with circular dependencies were configured.");
180                 } catch (AttributeResolverException e) {
181                         // This exception should be thrown, ignoring
182                 } catch (MalformedURLException e) {
183                         fail("Error in test specification: " + e.getMessage());
184                 }
185         }
186
187         public void testSourceNameMapping() {
188
189                 try {
190                         File file = new File("data/resolver7.xml");
191                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
192
193                         AAAttributeSet inputAttributes = new AAAttributeSet(new AAAttribute[]{new AAAttribute("myAffiliation")});
194
195                         AAAttributeSet outputAttributes = new AAAttributeSet(new AAAttribute[]{new AAAttribute("myAffiliation",
196                                         new Object[]{"member"})});
197
198                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
199                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
200
201                 } catch (AttributeResolverException e) {
202                         fail("Couldn't load attribute resolver: " + e.getMessage());
203                 } catch (MalformedURLException e) {
204                         fail("Error in test specification: " + e.getMessage());
205                 } catch (SAMLException e) {
206                         fail("Error creating SAML Attribute: " + e.getMessage());
207                 }
208         }
209
210         public void testMultipleDataConnectors() {
211
212                 try {
213                         File file = new File("data/resolver8.xml");
214                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
215
216                         AAAttributeSet inputAttributes = new AAAttributeSet(new AAAttribute[]{
217                                         new AAAttribute("urn:mace:dir:attribute-def:eduPersonPrincipalName"),
218                                         new AAAttribute("urn:mace:dir:attribute-def:eduPersonAffiliation"),
219                                         new AAAttribute("urn:mace:dir:attribute-def:eduPersonEntitlement")});
220
221                         AAAttributeSet outputAttributes = new AAAttributeSet(new AAAttribute[]{
222                                         new AAAttribute("urn:mace:dir:attribute-def:eduPersonPrincipalName",
223                                                         new Object[]{"mytestuser@example.edu"}, new ScopedStringValueHandler("example.edu")),
224                                         new AAAttribute("urn:mace:dir:attribute-def:eduPersonAffiliation", new Object[]{"member"}),
225                                         new AAAttribute("urn:mace:dir:attribute-def:eduPersonEntitlement",
226                                                         new Object[]{"urn:mace:example.edu:exampleEntitlement"})});
227
228                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
229
230                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
231
232                 } catch (AttributeResolverException e) {
233                         fail("Couldn't load attribute resolver: " + e.getMessage());
234                 } catch (MalformedURLException e) {
235                         fail("Error in test specification: " + e.getMessage());
236                 } catch (SAMLException e) {
237                         fail("Error creating SAML Attribute: " + e.getMessage());
238                 }
239         }
240
241         public void testAttributeDependency() {
242
243                 try {
244                         File file = new File("data/resolver9.xml");
245                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
246
247                         AAAttributeSet inputAttributes = new AAAttributeSet(new AAAttribute[]{new AAAttribute(
248                                         "urn:mace:dir:attribute-def:eduPersonScopedAffiliation")});
249
250                         AAAttributeSet outputAttributes = new AAAttributeSet(new AAAttribute[]{new AAAttribute(
251                                         "urn:mace:dir:attribute-def:eduPersonScopedAffiliation", new Object[]{"member@example.edu"},
252                                         new ScopedStringValueHandler("example.edu"))});
253
254                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
255
256                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
257
258                 } catch (AttributeResolverException e) {
259                         fail("Couldn't load attribute resolver: " + e.getMessage());
260                 } catch (MalformedURLException e) {
261                         fail("Error in test specification: " + e.getMessage());
262                 } catch (SAMLException e) {
263                         fail("Error creating SAML Attribute: " + e.getMessage());
264                 }
265         }
266
267         public void testMisLabeledDataConnector() {
268
269                 try {
270                         File file = new File("data/resolver11.xml");
271                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
272
273                         AAAttributeSet inputAttributes = new AAAttributeSet(new AAAttribute[]{new AAAttribute(
274                                         "urn:mace:dir:attribute-def:eduPersonScopedAffiliation")});
275
276                         AAAttributeSet outputAttributes = new AAAttributeSet();
277
278                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
279
280                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
281
282                 } catch (AttributeResolverException e) {
283                         fail("Couldn't load attribute resolver: " + e.getMessage());
284                 } catch (MalformedURLException e) {
285                         fail("Error in test specification: " + e.getMessage());
286                 } catch (SAMLException e) {
287                         fail("Error creating SAML Attribute: " + e.getMessage());
288                 }
289         }
290
291         public void testMisLabeledAttributeDefinition() {
292
293                 try {
294                         File file = new File("data/resolver10.xml");
295                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
296
297                         AAAttributeSet inputAttributes = new AAAttributeSet(new AAAttribute[]{new AAAttribute(
298                                         "urn:mace:dir:attribute-def:eduPersonScopedAffiliation")});
299
300                         AAAttributeSet outputAttributes = new AAAttributeSet();
301
302                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
303
304                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
305                 } catch (ClassCastException e) {
306                         fail("Failed to detect that an Attribute Definition was mislabeled as a Data Connector: " + e.getMessage());
307                 } catch (AttributeResolverException e) {
308                         fail("Couldn't load attribute resolver: " + e.getMessage());
309                 } catch (MalformedURLException e) {
310                         fail("Error in test specification: " + e.getMessage());
311                 } catch (SAMLException e) {
312                         fail("Error creating SAML Attribute: " + e.getMessage());
313                 }
314         }
315
316         public void testMultiLevelAttributeDependency() {
317
318                 try {
319                         File file = new File("data/resolver12.xml");
320                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
321
322                         AAAttributeSet inputAttributes = new AAAttributeSet(new AAAttribute[]{
323                                         new AAAttribute("urn:mace:dir:attribute-def:eduPersonScopedAffiliation"),
324                                         new AAAttribute("urn:mace:dir:attribute-def:eduPersonAffiliation"),
325                                         new AAAttribute("urn:mace:shibboleth:test:eduPersonAffiliation")});
326
327                         AAAttributeSet outputAttributes = new AAAttributeSet(new AAAttribute[]{
328                                         new AAAttribute("urn:mace:dir:attribute-def:eduPersonScopedAffiliation",
329                                                         new Object[]{"member@example.edu"}, new ScopedStringValueHandler("example.edu")),
330                                         new AAAttribute("urn:mace:dir:attribute-def:eduPersonAffiliation", new Object[]{"member"}),
331                                         new AAAttribute("urn:mace:shibboleth:test:eduPersonAffiliation", new Object[]{"member"})});
332
333                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
334
335                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
336
337                 } catch (AttributeResolverException e) {
338                         fail("Couldn't load attribute resolver: " + e.getMessage());
339                 } catch (MalformedURLException e) {
340                         fail("Error in test specification: " + e.getMessage());
341                 } catch (SAMLException e) {
342                         fail("Error creating SAML Attribute: " + e.getMessage());
343                 }
344         }
345
346         /**
347          * This method is reused by several tests that use different XML files as test data.
348          * 
349          * @param resolverFile
350          *            filename of a file containing data in the same format as resolver.xml.
351          * @param attributeFile
352          *            filename of a file containing output of the attribute resolution. The input file for attribute
353          *            resolution is specified in the resolverFile itself
354          * @param principal
355          *            name of the principal on whose behalf the resolution is done
356          * @param requester
357          *            the Shibboleth Target SHAR that is requesting the attribute resolution
358          */
359         private void simpleAttributeResolution(String resolverFile, String attributeFile, String principal,
360                         String requester, boolean sort) {
361
362                 try {
363                         // Create the attribute resolver
364                         File file = new File(resolverFile);
365                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
366
367                         // Create the output attributes file
368                         AttributesFile attrFile = new AttributesFile(attributeFile);
369
370                         // Read only the attribute names from the output file. The values are set by the resolver
371                         ResolverAttributeSet attrsToBeResolved = attrFile.getResolverAttributes(false);
372                         ar.resolveAttributes(new LocalPrincipal(principal), requester, null, attrsToBeResolved);
373
374                         // Read the attribute names and values from the output file
375                         ResolverAttributeSet expectedAttributes = attrFile.getResolverAttributes(true);
376
377                         if (sort) {
378                                 sort(attrsToBeResolved);
379                                 sort(expectedAttributes);
380                         }
381                         // Ensure that the values set by the resolver are the same as the ones outlined in the output file
382                         assertEquals("Attribute Resolver returned unexpected attribute set.", expectedAttributes, attrsToBeResolved);
383                 } catch (AttributeResolverException e) {
384                         fail("Couldn't load attribute resolver: " + e.getMessage());
385                 } catch (MalformedURLException e) {
386                         fail("Error in test specification: " + e.getMessage());
387                 } catch (IOException e) {
388                         fail("Error in test data: " + e.getMessage());
389                 } catch (SAMLException e) {
390                         fail("Error creating SAML attribute: " + e.getMessage());
391                 }
392         }
393
394         public void testAttrDef_RegEx_DN_CN_UID() {
395
396                 simpleAttributeResolution("data/attr-regex.resolver.1.xml", "data/attr-regex.output.1", "RegExTestUser",
397                                 "urn::test:luminis::sungardsct::com", DO_NOT_SORT);
398         }
399
400         public void testAttrDef_Mapped_PdsRole_EduPersonAffiliation() {
401
402                 simpleAttributeResolution("data/attr-mapped.resolver.1.xml", "data/attr-mapped.output.1", "MappedTestUser",
403                                 "urn::test:luminis::sungardsct::com", DO_SORT);
404         }
405
406         public void testAttrDef_Mapped_Role_EduPersonEntitlement() {
407
408                 simpleAttributeResolution("data/attr-mapped.resolver.2.xml", "data/attr-mapped.output.2", "MappedTestUser",
409                                 "urn::test:luminis::sungardsct::com", DO_SORT);
410         }
411
412         public void testAttrDef_Formatted_DateOfBirth() {
413
414                 simpleAttributeResolution("data/attr-format.resolver.1.xml", "data/attr-format.output.1",
415                                 "FormattedDateTestUser", "urn::test:luminis::sungardsct::com", DO_NOT_SORT);
416         }
417
418         public void testAttrDef_Formatted_Choice_GPA_Distinction() {
419
420                 simpleAttributeResolution("data/attr-format.resolver.2.xml", "data/attr-format.output.2", "FormattedTestUser",
421                                 "urn::test:luminis::sungardsct::com", DO_NOT_SORT);
422         }
423
424         public void testAttrDef_Composite_LabeledURI() {
425
426                 simpleAttributeResolution("data/attr-composite.resolver.1.xml", "data/attr-composite.output.1",
427                                 "CompositeTestUser", "urn::test:luminis::sungardsct::com", DO_NOT_SORT);
428         }
429
430         // Failing Test cases
431         // How to test that improperly configured definitions will fail to load. Can we check for the specific error?
432         // 
433         /**
434          * 1. RegEx - Custom Value Handler (reverses the characters) can be used 2. Mapped - Custom Value Handler (reverses
435          * the characters) can be used 3. Formatted - Custom Value Handler (reverses the characters) can be used 4.
436          * Composite - Custom Value Handler (reverses the characters) can be used - unordered values should fail - Behavior
437          * with unequal number of values
438          */
439
440         /**
441          * Sort the attribute values in the AAAttribute so that equals comparison works as intended
442          */
443         private void sort(ResolverAttributeSet attrSet) {
444
445                 for (ResolverAttributeIterator iter = attrSet.resolverAttributeIterator(); iter.hasNext();) {
446                         ResolverAttribute attr = iter.nextResolverAttribute();
447                         if (attr instanceof AAAttribute) {
448                                 ArrayList values = new ArrayList();
449                                 for (Iterator valuesIterator = attr.getValues(); valuesIterator.hasNext();) {
450                                         values.add(valuesIterator.next());
451                                 }
452                                 Object[] sortedValues = values.toArray();
453                                 Arrays.sort(sortedValues);
454
455                                 ((AAAttribute) attr).setValues(sortedValues);
456                         }
457                 }
458         }
459
460 }