View Javadoc

1   /*
2    * Copyright 2009 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.idp;
18  
19  import java.io.IOException;
20  import java.io.PrintWriter;
21  import java.net.InetAddress;
22  import java.net.UnknownHostException;
23  
24  import javax.servlet.ServletConfig;
25  import javax.servlet.ServletException;
26  import javax.servlet.http.HttpServlet;
27  import javax.servlet.http.HttpServletRequest;
28  import javax.servlet.http.HttpServletResponse;
29  
30  import org.apache.commons.httpclient.HttpStatus;
31  import org.joda.time.DateTime;
32  import org.joda.time.Duration;
33  import org.joda.time.chrono.ISOChronology;
34  import org.joda.time.format.DateTimeFormatter;
35  import org.joda.time.format.ISODateTimeFormat;
36  import org.opensaml.xml.security.x509.X509Credential;
37  import org.opensaml.xml.util.Base64;
38  import org.opensaml.xml.util.DatatypeHelper;
39  import org.opensaml.xml.util.LazyList;
40  import org.slf4j.Logger;
41  import org.slf4j.LoggerFactory;
42  
43  import edu.internet2.middleware.shibboleth.common.attribute.resolver.AttributeResolutionException;
44  import edu.internet2.middleware.shibboleth.common.attribute.resolver.AttributeResolver;
45  import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfiguration;
46  import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfigurationManager;
47  import edu.internet2.middleware.shibboleth.idp.util.HttpServletHelper;
48  import edu.internet2.middleware.shibboleth.idp.util.IPRange;
49  
50  /** A Servlet for displaying the status of the IdP. */
51  public class StatusServlet extends HttpServlet {
52  
53      /** Serial version UID. */
54      private static final long serialVersionUID = -5280549109235107879L;
55  
56      private final String IP_PARAM_NAME = "AllowedIPs";
57      
58      private final Logger log = LoggerFactory.getLogger(StatusServlet.class);
59  
60      private LazyList<IPRange> allowedIPs;
61  
62      /** Formatter used when print date/times. */
63      private DateTimeFormatter dateFormat;
64  
65      /** Time the IdP started up. */
66      private DateTime startTime;
67  
68      /** Attribute resolver used by the IdP. */
69      private AttributeResolver<?> attributeResolver;
70  
71      /** Relying party configuration manager used by the IdP. */
72      private RelyingPartyConfigurationManager rpConfigManager;
73  
74      /** {@inheritDoc} */
75      public void init(ServletConfig config) throws ServletException {
76          super.init(config);
77  
78          allowedIPs = new LazyList<IPRange>();
79  
80          String cidrBlocks = DatatypeHelper.safeTrimOrNullString(config.getInitParameter(IP_PARAM_NAME));
81          if (cidrBlocks != null) {
82              for (String cidrBlock : cidrBlocks.split(" ")) {
83                  allowedIPs.add(IPRange.parseCIDRBlock(cidrBlock));
84              }
85          }
86  
87          dateFormat = ISODateTimeFormat.dateTimeNoMillis();
88          startTime = new DateTime(ISOChronology.getInstanceUTC());
89          attributeResolver = HttpServletHelper.getAttributeResolver(config.getServletContext());
90          rpConfigManager = HttpServletHelper.getRelyingPartyConfirmationManager(config.getServletContext());
91      }
92  
93      /** {@inheritDoc} */
94      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
95          if (!isAuthenticated(request)) {
96              response.sendError(HttpStatus.SC_UNAUTHORIZED);
97              return;
98          }
99  
100         response.setContentType("text/plain");
101         PrintWriter output = response.getWriter();
102 
103         printOperatingEnvironmentInformation(output);
104         output.println();
105         printIdPInformation(output);
106         output.println();
107         printRelyingPartyConfigurationsInformation(output, request.getParameter("relyingParty"));
108 
109         output.flush();
110     }
111 
112     /**
113      * Checks whether the client is authenticated.
114      * 
115      * @param request client request
116      * 
117      * @return true if the client is authenticated, false if not
118      */
119     protected boolean isAuthenticated(HttpServletRequest request) throws ServletException {
120         log.debug("Attempting to authenticate client '{}'", request.getRemoteAddr());
121         try {
122             InetAddress clientAddress = InetAddress.getByName(request.getRemoteAddr());
123 
124             for (IPRange range : allowedIPs) {
125                 if (range.contains(clientAddress)) {
126                     return true;
127                 }
128             }
129 
130             return false;
131         } catch (UnknownHostException e) {
132             throw new ServletException(e);
133         }
134     }
135 
136     /**
137      * Prints out information about the operating environment. This includes the operating system name, version and
138      * architecture, the JDK version, available CPU cores, memory currently used by the JVM process, the maximum amount
139      * of memory that may be used by the JVM, and the current time in UTC.
140      * 
141      * @param out output writer to which information will be written
142      */
143     protected void printOperatingEnvironmentInformation(PrintWriter out) {
144         Runtime runtime = Runtime.getRuntime();
145         DateTime now = new DateTime(ISOChronology.getInstanceUTC());
146 
147         out.println("### Operating Environment Information");
148         out.println("operating_system: " + System.getProperty("os.name"));
149         out.println("operating_system_version: " + System.getProperty("os.version"));
150         out.println("operating_system_architecture: " + System.getProperty("os.arch"));
151         out.println("jdk_version: " + System.getProperty("java.version"));
152         out.println("available_cores: " + runtime.availableProcessors());
153         out.println("used_memory: " + runtime.totalMemory() / 1048576 + "MB");
154         out.println("maximum_memory: " + runtime.maxMemory() / 1048576 + "MB");
155         out.println("start_time: " + startTime.toString(dateFormat));
156         out.println("current_time: " + now.toString(dateFormat));
157         out.println("uptime: " + (now.getMillis() - startTime.getMillis()) + "ms");
158     }
159 
160     /**
161      * Prints out general IdP information. This includes IdP version, start up time, and whether the attribute resolver
162      * is currently operational.
163      * 
164      * @param out output writer to which information will be written
165      */
166     protected void printIdPInformation(PrintWriter out) {
167         Package pkg = Version.class.getPackage();
168 
169         out.println("### Identity Provider Information");
170         out.println("idp_version: " + pkg.getImplementationVersion());
171         out.println("idp_start_time: " + startTime.toString(dateFormat));
172         try {
173             attributeResolver.validate();
174             out.println("attribute_resolver_valid: " + Boolean.TRUE);
175         } catch (AttributeResolutionException e) {
176             out.println("attribute_resolver_valid: " + Boolean.FALSE);
177         }
178     }
179 
180     /**
181      * Prints information about relying party configurations. If the given relying party is null then the configuration
182      * for all relying parties is printed. If the relying party ID is not null then the relying party configurations for
183      * that entity is printed.
184      * 
185      * @param out output writer to which information will be written
186      * @param relyingPartyId entity ID of the relying party whose configuration should be printed
187      */
188     protected void printRelyingPartyConfigurationsInformation(PrintWriter out, String relyingPartyId) {
189         out.println("### Relying Party Configurations");
190 
191         if (relyingPartyId == null) {
192             for (RelyingPartyConfiguration config : rpConfigManager.getRelyingPartyConfigurations().values()) {
193                 printRelyingPartyConfigurationInformation(out, config);
194                 out.println();
195             }
196         } else {
197             RelyingPartyConfiguration config = rpConfigManager.getRelyingPartyConfiguration(relyingPartyId);
198             printRelyingPartyConfigurationInformation(out, config);
199             out.println();
200         }
201     }
202 
203     /**
204      * Prints out the information for a specific relying party configuration. This information includes the relying
205      * party or relying party group ID, the entity ID of the IdP when it responds when using this configuration, the
206      * default authentication method used for this config, and configured communication profiles.
207      * 
208      * @param out output writer to which information will be written
209      * @param config the relying party configuration
210      */
211     protected void printRelyingPartyConfigurationInformation(PrintWriter out, RelyingPartyConfiguration config) {
212         out.println("relying_party_id: " + config.getRelyingPartyId());
213         out.println("idp_entity_id: " + config.getProviderId());
214 
215         if (config.getDefaultAuthenticationMethod() != null) {
216             out.println("default_authentication_method: " + config.getDefaultAuthenticationMethod());
217         } else {
218             out.println("default_authentication_method: none");
219         }
220 
221         try {
222             X509Credential signingCredential = (X509Credential) config.getDefaultSigningCredential();
223             out
224                     .println("default_signing_tls_key: "
225                             + Base64.encodeBytes(signingCredential.getEntityCertificate().getEncoded(),
226                                     Base64.DONT_BREAK_LINES));
227         } catch (Throwable t) {
228             // swallow error
229         }
230 
231         for (String profileId : config.getProfileConfigurations().keySet()) {
232             out.println("configured_communication_profile: " + profileId);
233         }
234     }
235 }