Create parser pool interface and move current pool to an implementation of this inter...
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / utils / ResolverTest.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.utils;
18
19 import jargs.gnu.CmdLineParser;
20
21 import java.io.PrintStream;
22 import java.io.PrintWriter;
23 import java.io.StringWriter;
24 import java.security.Principal;
25 import java.util.Collection;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.Map;
29
30 import javax.xml.transform.OutputKeys;
31 import javax.xml.transform.Transformer;
32 import javax.xml.transform.TransformerFactory;
33 import javax.xml.transform.dom.DOMSource;
34 import javax.xml.transform.stream.StreamResult;
35
36 import org.apache.log4j.ConsoleAppender;
37 import org.apache.log4j.Level;
38 import org.apache.log4j.Logger;
39 import org.apache.log4j.PatternLayout;
40 import org.opensaml.SAMLException;
41 import org.w3c.dom.Document;
42 import org.w3c.dom.Element;
43 import org.w3c.dom.Node;
44 import org.w3c.dom.NodeList;
45
46 import edu.internet2.middleware.shibboleth.aa.AAAttribute;
47 import edu.internet2.middleware.shibboleth.aa.arp.ArpEngine;
48 import edu.internet2.middleware.shibboleth.aa.arp.ArpException;
49 import edu.internet2.middleware.shibboleth.aa.arp.ArpProcessingException;
50 import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeResolver;
51 import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeResolverException;
52 import edu.internet2.middleware.shibboleth.common.LocalPrincipal;
53 import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
54 import edu.internet2.middleware.shibboleth.idp.IdPConfig;
55 import edu.internet2.middleware.shibboleth.idp.IdPConfigLoader;
56
57 /**
58  * Utility for testing an Attribute Resolver configuration.
59  * 
60  * @author Walter Hoehn
61  * @author Noah Levitt
62  */
63 public class ResolverTest {
64
65         private static boolean debug = false;
66         private static String resolverxml = null;
67         private static String idpXml = null;
68         private static String requester = null;
69         private static String responder = null;
70         private static String user = null;
71         private static AttributeResolver resolver = null;
72         private static ArpEngine arpEngine = null;
73
74         public static void main(String[] args) {
75
76                 parseCommandLine(args);
77                 initializeResolver();
78                 Map<String, AAAttribute> attributeSet = createAttributeSet();
79                 resolveAttributes(attributeSet);
80
81                 System.out.println("Received the following from the Attribute Resolver:");
82                 System.out.println();
83                 printAttributes(System.out, attributeSet.values());
84         }
85
86         private static void resolveAttributes(Map<String, AAAttribute> attributeSet) {
87
88                 Principal principal = new LocalPrincipal(user);
89
90                 resolver.resolveAttributes(principal, requester, responder, attributeSet);
91
92                 try {
93                         if (arpEngine != null) {
94                                 arpEngine.filterAttributes(attributeSet.values(), principal, requester);
95                         }
96                 } catch (ArpProcessingException e) {
97                         System.err.println("Error applying Attribute Release Policy: " + e.getMessage());
98                         System.exit(1);
99                 }
100         }
101
102         private static void parseCommandLine(String[] args) {
103
104                 CmdLineParser parser = new CmdLineParser();
105
106                 CmdLineParser.Option helpOption = parser.addBooleanOption('h', "help");
107                 CmdLineParser.Option debugOption = parser.addBooleanOption('d', "debug");
108                 CmdLineParser.Option idpXmlOption = parser.addStringOption('\u0000', "idpXml");
109                 CmdLineParser.Option userOption = parser.addStringOption('u', "user");
110                 CmdLineParser.Option requesterOption = parser.addStringOption('r', "requester");
111                 CmdLineParser.Option responderOption = parser.addStringOption('i', "responder");
112                 CmdLineParser.Option resolverxmlOption = parser.addStringOption('\u0000', "resolverxml");
113                 CmdLineParser.Option fileOption = parser.addStringOption('f', "file"); // deprecated
114
115                 try {
116                         parser.parse(args);
117                 } catch (CmdLineParser.OptionException e) {
118                         System.out.println(e.getMessage());
119                         printUsage(System.out);
120                         System.exit(1);
121                 }
122
123                 Boolean helpEnabled = (Boolean) parser.getOptionValue(helpOption);
124                 if (helpEnabled != null && helpEnabled.booleanValue()) {
125                         printUsage(System.out);
126                         System.exit(0);
127                 }
128
129                 Boolean debugEnabled = ((Boolean) parser.getOptionValue(debugOption));
130                 if (debugEnabled != null) {
131                         debug = debugEnabled.booleanValue();
132                 }
133
134                 // if --resolverxml and --file both specified, silently use --resolverxml
135                 resolverxml = (String) parser.getOptionValue(resolverxmlOption);
136                 if (resolverxml == null) {
137                         resolverxml = (String) parser.getOptionValue(fileOption);
138                 }
139
140                 idpXml = (String) parser.getOptionValue(idpXmlOption);
141
142                 user = (String) parser.getOptionValue(userOption);
143                 requester = (String) parser.getOptionValue(requesterOption);
144                 responder = (String) parser.getOptionValue(responderOption);
145
146                 configureLogging(debug);
147                 checkRequired();
148         }
149
150         /**
151          * Ensures that all required parameters were specified and successfully parsed.
152          */
153         private static void checkRequired() {
154
155                 if (user == null) {
156                         System.out.println("Missing required parameter --user.");
157                         System.out.println();
158                         printUsage(System.out);
159                         System.exit(1);
160                 }
161                 if ((resolverxml == null && idpXml == null) || (resolverxml != null && idpXml != null)) {
162                         System.out.println("Exactly one of --idpXml and --resolverxml is required.");
163                         System.out.println();
164                         printUsage(System.out);
165                         System.exit(1);
166                 }
167         }
168
169         private static Map<String, AAAttribute> createAttributeSet() {
170
171                 Collection<String> attributes = resolver.listRegisteredAttributeDefinitionPlugIns();
172                 Map<String, AAAttribute> attributeSet = new HashMap<String, AAAttribute>();
173
174                 for (String attrName : attributes) {
175                         try {
176                                 attributeSet.put(attrName, new AAAttribute(attrName));
177                         } catch (SAMLException e) {
178                                 System.err.println("Error creating AAAttribute (" + attrName + "): " + e.getMessage());
179                                 System.exit(1);
180                         }
181                 }
182
183                 return attributeSet;
184         }
185
186         private static void initializeResolver() {
187
188                 if (idpXml != null) {
189                         try {
190                                 Document idpConfig = IdPConfigLoader.getIdPConfig(idpXml);
191                                 IdPConfig configuration = new IdPConfig(idpConfig.getDocumentElement());
192
193                                 resolver = new AttributeResolver(configuration);
194
195                                 NodeList itemElements = idpConfig.getDocumentElement().getElementsByTagNameNS(
196                                                 IdPConfig.configNameSpace, "ReleasePolicyEngine");
197
198                                 if (itemElements.getLength() > 1) {
199                                         System.err
200                                                         .println("Warning: encountered multiple <ReleasePolicyEngine> configuration elements in ("
201                                                                         + idpXml + "). Using first...");
202                                 }
203
204                                 if (itemElements.getLength() < 1) {
205                                         arpEngine = new ArpEngine();
206                                 } else {
207                                         arpEngine = new ArpEngine((Element) itemElements.item(0));
208                                 }
209
210                         } catch (ShibbolethConfigurationException e) {
211                                 System.err.println("Error loading IdP configuration file (" + idpXml + "): " + e.getMessage());
212                                 System.exit(1);
213                         } catch (AttributeResolverException e) {
214                                 System.err.println("Error initializing the Attribute Resolver: " + e.getMessage());
215                                 System.exit(1);
216                         } catch (ArpException e) {
217                                 System.err.println("Error initializing the ARP Engine: " + e.getMessage());
218                                 System.exit(1);
219                         }
220                 } else {
221                         try {
222                                 resolver = new AttributeResolver(resolverxml);
223                         } catch (AttributeResolverException e) {
224                                 System.err.println("Error initializing the Attribute Resolver: " + e.getMessage());
225                                 System.exit(1);
226                         }
227                 }
228         }
229
230         private static void printAttributes(PrintStream out, Collection<AAAttribute> attributeSet) {
231
232                 try {
233                         for (Iterator<AAAttribute> iterator = attributeSet.iterator(); iterator.hasNext();) {
234                                 AAAttribute attribute = iterator.next();
235                                 Node node = attribute.toDOM();
236
237                                 if (!(node instanceof Element)) {
238                                         System.err.println("Received bad Element data from SAML library.");
239                                         System.exit(1);
240                                 }
241
242                                 TransformerFactory factory = TransformerFactory.newInstance();
243                                 DOMSource source = new DOMSource(node);
244                                 Transformer transformer = factory.newTransformer();
245                                 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
246                                 StringWriter stringWriter = new StringWriter();
247                                 StreamResult result = new StreamResult(stringWriter);
248                                 transformer.transform(source, result);
249                                 out.println(stringWriter.toString());
250
251                                 out.println();
252                         }
253                 } catch (Exception e) {
254                         System.err.println("Error creating SAML attribute: " + e.getMessage());
255                         System.exit(1);
256                 }
257         }
258
259         private static void configureLogging(boolean debugEnabled) {
260
261                 ConsoleAppender rootAppender = new ConsoleAppender();
262                 rootAppender.setWriter(new PrintWriter(System.out));
263                 rootAppender.setName("stdout");
264                 Logger.getRootLogger().addAppender(rootAppender);
265
266                 if (debugEnabled) {
267                         Logger.getRootLogger().setLevel(Level.DEBUG);
268                         rootAppender.setLayout(new PatternLayout("%-5p %-41X{serviceId} %d{ISO8601} (%c:%L) - %m%n"));
269                 } else {
270                         Logger.getRootLogger().setLevel(Level.INFO);
271                         Logger.getLogger("edu.internet2.middleware.shibboleth.aa.attrresolv").setLevel(Level.WARN);
272                         rootAppender.setLayout(new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN));
273                 }
274                 Logger.getLogger("org.apache.xml.security").setLevel(Level.OFF);
275         }
276
277         private static void printUsage(PrintStream out) {
278
279                 // out.println("Tests an AA Attribute Resolver configuration.");
280                 out.println("Usage: resolvertest --user=USER {--idpXml=URL|--resolverxml=URL} [OPTION...]");
281                 out.println();
282                 out.println("Options:");
283                 out.println("  -h, --help                Print usage information");
284                 out.println("  -d, --debug               Run in debug mode");
285                 out.println("  --idpXml=FILEURL          URL of the IdP configuration file. Attributes");
286                 out.println("                              will be filtered according to the Attribute Release");
287                 out.println("                              Policy (ARP) specified in the configuration file");
288                 out.println("  --resolverxml=FILEURL     URL of the resolver configuration file. No ARP");
289                 out.println("                              filtering will be done");
290                 out.println("  --user=USER               User for whom attributes should be resolved");
291                 out.println("  --requester=REQUESTER     Name of the requester (SP). Emulates");
292                 out.println("                              unauthenticated requester if not specified");
293                 out.println("  --responder=RESPONDER     Name of the responder (IdP).");
294                 out.println("  --resource=URL            URL of the resource. Only attributes available");
295                 out.println("                              to any resource will be returned if not specified");
296         }
297 }