View Javadoc

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