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)