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