You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ranger.apache.org by "kirby zhou (Jira)" <ji...@apache.org> on 2022/03/02 12:47:00 UTC

[jira] [Commented] (RANGER-3619) REST API should return 403 when authenticated client is not allowed to access API.

    [ https://issues.apache.org/jira/browse/RANGER-3619?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17500115#comment-17500115 ] 

kirby zhou commented on RANGER-3619:
------------------------------------

[https://reviews.apache.org/r/73881/]

 

> REST API should return 403 when authenticated client is not allowed to access API.
> ----------------------------------------------------------------------------------
>
>                 Key: RANGER-3619
>                 URL: https://issues.apache.org/jira/browse/RANGER-3619
>             Project: Ranger
>          Issue Type: Bug
>          Components: Ranger
>    Affects Versions: 3.0.0, 2.2.0
>            Reporter: kirby zhou
>            Priority: Major
>
> REST API should return 403-Forbidden when authenticated client is not allowed to access API to avoid crash Ranger Clients.
>  
> Now, some API returns 401-Unauthorized instead of 403-Forbidden when client is already passed authentication but now allowed to do something.
> In general, this will not cause any serious problems. However, there is a flaw in the SPNEGO protocol implementation of Java HTTPUrlConnection. It causes the Client to throw an unexpected exception. This will trouble the operators and developers.
>  
> Let me show you how it happens:
>  
> For example:
>  
> The RangerAdminClient inside KMS  want to access API "/service/secure/policies/download", but the principal is not in the allowlist.
>  
>  # RangerAdminClient is based on Jersey-Client
>  # JerseyClient sends a HTTP-request to Ranger Service without authentication information
>  # Tomcat/Spring inside Ranger returns 401 with HTTP header “WWW-Authentication: Neogotiate”
>  # JerseyClient sends request again with Kerberos/SPNEGO authentication tokens.
>  # Tomcat/Spring inside Ranger accept the authentication, then call ServiceRest::getSecureServicePoliciesIfUpdated to reply the API calling.
>  # ServiceRest::getSecureServicePoliciesIfUpdated checks allowlist of “kms service”, and refuse client with 401.
>  # Tomcat/Spring inside Ranger returns 401 with HTTP header “WWW-Authentication: Neogotiate….” for notifying RangerAdminClient the authentication is passed.
>  
> Now, there is a malformed state. HTTP-status code told client authenticate is failed, but HTTP header told client authentication is passed.
>  
> In the RangerAdminClient side, 
>  
>  # sun.net.www.protocol.http.HttpURLConnection.getInputStream0() see the second 401.
>  # 'inNegotiate' = true, so it is in the progress of _Negotiate._
>  # It checks that: if "WWW-Authenticate: Negotiate" exist then disable negotiate for following code to avoid try {_}Negotiate once again{_}.
>  # But "WWW-Authenticate: Negotiate xczsd324…" does not the rule above.
>  # So HttpURLConnection calls AuthenticationInfo.sendHeaders to generate a new request header.
>  # Wow, Null exception happens.
>  # Logs "ERROR RangerAdminRESTClient - Error getting policies; Received NULL response!!. secureMode=true, user=… (auth:KERBEROS), serviceName=kmsdev"
>  # Log of KMS: "ERROR RangerAdminRESTClient - Failed to get response, Error is : java.lang.RuntimeException: java.lang.NullPointerException"
>  
> This log makes admin confused.
>  
>  
> {code:java}
> //ServiceRest::getServicePoliciesIfUpdated
> if (isAllowed) {
> //...
> } else {
>    httpCode = HttpServletResponse.SC_UNAUTHORIZED;
> }
>  {code}
> {code:java}
> // sun.net.www.protocol.http.HttpURLConnection.getInputStream0()
> // Read comments labeled "Failed Negotiate" for details.
> boolean dontUseNegotiate = false;
> Iterator<String> iter = responses.multiValueIterator("WWW-Authenticate");
> while (iter.hasNext()) {
>     String value = iter.next().trim();
>     if (value.equalsIgnoreCase("Negotiate") ||
>             value.equalsIgnoreCase("Kerberos")) {
>         if (!inNegotiate) {
>             inNegotiate = true;
>         } else {
>             dontUseNegotiate = true;
>             doingNTLM2ndStage = false;
>             serverAuthentication = null;
>         }
>         break;
>     }
> }
> /**
>  * Failed Negotiate
>  *
>  * In some cases, the Negotiate auth is supported for the
>  * remote host but the negotiate process still fails (For
>  * example, if the web page is located on a backend server
>  * and delegation is needed but fails). The authentication
>  * process will start again, and we need to detect this
>  * kind of failure and do proper fallback (say, to NTLM).
>  *
>  * In order to achieve this, the inNegotiate flag is set
>  * when the first negotiate challenge is met (and reset
>  * if authentication is finished). If a fresh new negotiate
>  * challenge (no parameter) is found while inNegotiate is
>  * set, we know there's a failed auth attempt recently.
>  * Here we'll ignore the header line so that fallback
>  * can be practiced.
>  *
>  * inNegotiateProxy is for proxy authentication.
>  */
>   {code}
>  
>  
>  
>  



--
This message was sent by Atlassian Jira
(v8.20.1#820001)