Class ClientSecurity

java.lang.Object
com.mapr.security.client.ClientSecurity

public class ClientSecurity extends Object
The ClientSecurity class. This is the pure Java implementation of the client-side API using MapR ticket authentication, used for REST API calls. The MapR challenge-response handshake allows for mutual authentication of both server and client using the MapR ticket-based security model.

The MapR challenge-response handshake follows the RFC 7235/2616 standard. A brief description of the handshake is given here. More information can be found in https://tools.ietf.org/html/rfc7235#section-4.1 and RFC 2616 - Hypertext Transfer Protocol. See https://tools.ietf.org/html/rfc2616#page-107. If the server receives a request for an access-protected object, and if an acceptable "Authorization" header has not been sent, the server responds with a "401 Unauthorized" status code, and a "WWW- Authenticate:" header as per the framework described in [RFC2616]. For MapR ticket authentication, the value of WWW-Authenticate include MAPR-Negotiate. For example:


 HTTP/1.1 401 Unauthorized
 WWW-Authenticate: MAPR-Negotiate
 
If the client application receives a "401 Unauthorized" response for a REST API request, it should parse the header to see if it contains the WWW-Authenticate property with the value starting with MAPR-Negotiate, and start the negotiation process to obtain an authentication token. The client should also start the negotiation process to obtain an authentication token for the first time.

Assuming that the client has already done a "maprlogin password" to obtain a valid ticket for the cluster, the first phase of the two-phase MapR challenge-response authentication is to call the generateChallenge() method:


 ClientSecurity cs = new ClientSecurity();
 String challengeString = cs.generateChallenge ();
 
The returned challenge string and encrypted ticket is sent as an HTTP option ("OPTIONS") using the "Authorization" header with the MAPR-Negotiate property to the MapR service. An example of how to do this can be found in the com.mapr.security.client.examples.MapRClient class, but is outside the scope of this API. An example of a Base64 encoded challenge string is as follows:
 
 CihNcW/sDyVx63r25FJF0vuWNjAsdVrL1HrUivPYY8vdSelThGOPnd8zEmYCCAEVPQhUXvfjiFLP9xOIBsEGjZv4wwhZsk3ho2+lrDKFjWAHjnBqd7yQuqa+YSY7etfxkg1XK+izqqRjXkFo7zNST6swW7VmMJyo27CftvXv6wV3EFmJqcHV6ugJ3EjlHqtxlqY=
 
Using this sample challenge string, the request header looks something like this:
 
 Authorization: MAPR-Negotiate CihNcW/sDyVx63r25FJF0vuWNjAsdVrL1HrUivPYY8vdSelThGOPnd8zEmYCCAEVPQhUXvfjiFLP9xOIBsEGjZv4wwhZsk3ho2+lrDKFjWAHjnBqd7yQuqa+YSY7etfxkg1XK+izqqRjXkFo7zNST6swW7VmMJyo27CftvXv6wV3EFmJqcHV6ugJ3EjlHqtxlqY=
 
If the server successfully validates the challenge, it will return a status of HTTP/1.1 200 OK, together with a response to the challenge in using the "Authorization" header with the "MAPR-Negotiate" property. This would look something like this:
 
 HTTP/1.1 200 OK
 Authorization: MAPR-Negotiate WMlqqIt8Q5dcVo9wOtfVgBoSsbW8v/WQS0JWfGElUtPDb04hkQ/Zf26Fw7k=
 
Upon receiving the response from the server, the client application should verify that the response is HTTP/1.1 200 OK, and that the response message contains the "Authorization" header with the "MAPR-Negotiate" property. It should then extract the Base64-encoded response to the challenge that is in the "MAPR-Negotiate" property from the response message. In our example, this is the string
 
 WMlqqIt8Q5dcVo9wOtfVgBoSsbW8v/WQS0JWfGElUtPDb04hkQ/Zf26Fw7k=
 
 
The client application should then pass this string into the validateServerResponseToChallenge method:
 
 boolean isValidResponseToChallenge = validateServerResponseToChallenge (responseToChallenge);
 
 
If this method returns without throwing an exception, then the server response is successfully validated, and this completes the second and final phase of the challenge-response authentication.
  • Field Details

    • WWW_AUTHENTICATE

      public static final String WWW_AUTHENTICATE
      The "WWW-Authenticate" response header. Used to determine if we are in the negotiation phase. If the server receives a request for an access-protected object, and if an acceptable "Authorization" header has not been sent, the server responds with a "401 Unauthorized" status code, and a "WWW- Authenticate:" header as per the framework described in [RFC2616]. For MapR ticket authentication, the relevant headers would look like this:
       
       HTTP/1.1 401 Unauthorized
       WWW-Authenticate: MAPR-Negotiate
       
       
      The client should parse the header to see if it contains the WWW-Authenticate property with the value starting with MAPR-Negotiate, and start the negotiation process.
      See Also:
    • AUTHORIZATION

      public static final String AUTHORIZATION
      The HTTP "Authorization" request header. As per RFC 2616 (superseded by 7235), a user agent that wishes to authenticate itself with a server usually, but not necessarily, after receiving a 401 response, does so by including an Authorization request-header field with the request. The Authorization field value consists of credentials containing the authentication information of the user agent for the realm of the resource being requested. For MapR ticket authentication, this is the token obtained after successfully completing the challenge-response authentication. Upon receipt of the response containing a "WWW-Authenticate" header from the server, the client is expected to retry the HTTP request, passing a HTTP "Authorization" header line. See https://tools.ietf.org/html/rfc2616#page-107.
      See Also:
    • WWW_ERR_AUTHENTICATE

      public static final String WWW_ERR_AUTHENTICATE
      HTTP header used by the MAPR server end-point during an authentication sequence in case of error. Example: HTTP/1.1 403 Forbidden WWW-MAPR-Err-Authenticate Value: [Bad server key]
      See Also:
    • NEGOTIATE

      public static final String NEGOTIATE
      HTTP header prefix used by the MAPR client/server end-points during an authentication sequence. See the comments for WWW_AUTHENTICATE (WWW-Authenticate).
      See Also:
    • CLUSTER_CONFIG_LOCATION

      public static final String CLUSTER_CONFIG_LOCATION
      Location of the mapr-clusters.conf file relative to the installation directory. The first line of this file is used to determine the default cluster name and whether or not the cluster is secure. This is at /conf/mapr-clusters.conf.
      See Also:
    • DEFAULT_INSTALL_LOCATION

      public static final String DEFAULT_INSTALL_LOCATION
      Default installation location if the MAPR_HOME environment variable is not set. This is /opt/mapr
      See Also:
  • Constructor Details

    • ClientSecurity

      public ClientSecurity()
      Constructor. Parses the mapr-clusters.conf to determine the cluster name and whether security is enabled Since no cluster is specified, the default cluster that appears in the first line of mapr-clusters.conf is used
    • ClientSecurity

      public ClientSecurity(String clusterName)
      Constructor. Parses the mapr-clusters.conf to determine the cluster name and whether security is enabled. Uses the cluster name passed into the parameter as the cluster for all methods in the class. You need a different instance of this class to access different clusters
      Parameters:
      clusterName - The cluster name
  • Method Details

    • isSecurityEnabled

      public boolean isSecurityEnabled()
      Returns the security status for the current cluster. To determine this, we look line of mapr-clusters.conf with the cluster name matching the cluster name passed in the constructor, and look for the secure=true flag. If set to true, then security is enabled for the cluster, otherwise security is not enabled. The ClientSecurity class is only applicable for secure clusters.
      Returns:
      Returns true if security is enabled for the cluster, false otherwise.
    • isClusterNameValid

      public boolean isClusterNameValid()
      Returns true if the cluster name is valid, false otherwise. The cluster name is valid if there is an entry in mapr-cluster.conf for this cluster
      Returns:
      Returns true if the cluster name is valid, false otherwise.
    • getUserTicketAndKeyFileLocation

      public String getUserTicketAndKeyFileLocation() throws MapRClientSecurityException
      Obtains the full path name of the file containing the user ticket. This is determined as follows:
      • If the environment variable MAPR_TICKETFILE_LOCATION is set, then return the value of this environment variable.
      • Otherwise, the default location of the user ticket is as follows:
        • For Windows, this is at %TEMP%\maprticket_<username>. Example: C:\Temp\maprticket_joe.
        • For all other operating systems, this is at /tmp/maprticket_<uid> where <uid> is the effective UID of calling process.
      Pure Java implementation of the Security::GetUserTicketAndKeyFileLocation C API in src/fs/common/credentials.h
      Returns:
      The full path name of the file containing the user ticket.
      Throws:
      MapRClientSecurityException - Thrown when the location of the user ticket cannot be determined
    • generateChallenge

      public String generateChallenge() throws MapRClientSecurityException
      Evaluates the challenge from the MapR user ticket. Call this method to return a Base64-encoded string that can be used as an authentication string in a REST API call with the MAPR-Negotiate property. For example:
       
       ClientSecurity cs = new ClientSecurity();
       String authRequestBytes = cs.generateChallenge();
       
      Returns:
      The encrypted challenge string as a Base-64 encoded string
      Throws:
      MapRClientSecurityException - Thrown for various errors, such as user ticket is invalid or cannot be found, or the challenge cannot be derived from the user ticket
    • hasValidTicket

      public boolean hasValidTicket() throws MapRClientSecurityException
      Determines if the user has a valid ticket for the cluster specified in the parameter.
      Returns:
      Returns true if the user has a valid ticket for the cluster, false otherwise.
      Throws:
      MapRClientSecurityException - Thrown for various error situations, for example, when the ticket cannot be found, or the cluster name is invalid.
    • getClusterName

      public String getClusterName()
      Returns the cluster name. This is the cluster name that is set in the constructor
      Returns:
      The cluster name as an ASCII string. This is the cluster name from the first line of mapr-clusters.conf
    • validateServerResponseToChallenge

      public boolean validateServerResponseToChallenge(String responseToChallenge) throws MapRClientSecurityException
      Given the response from the server to the challenge, validates the response to the challenge. The server response is the Base-64 encoded string after the MAPR-Negotiate property in the Authorization header. It is the responsibility of the client application to extract the response to the challenge from the header and pass it in to this method as the second phase of the challenge-response negotiation. A sample header looks like this:
       
       HTTP/1.1 200 OK
       Authorization: MAPR-Negotiate M0GtfTQNSVVzOOtTFI8cgA5MON5cb1beloL+C3k6tl9lY16VRrA6GEJCSag=
       
       
      In this example, the input to this method would be the following Base64-encoded string:
       
       M0GtfTQNSVVzOOtTFI8cgA5MON5cb1beloL+C3k6tl9lY16VRrA6GEJCSag=
       
       
      Parameters:
      responseToChallenge - The Base64-encoded string giving the server response to the challenge
      Returns:
      Returns true if the server response is present and valid. Otherwise, a MapRClientSecurityException is thrown with the error message.
      Throws:
      MapRClientSecurityException - If the server response to the challenge-response negotiation is either not present or not valid