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 }