Bug 998033 - Python-rhsm should handle unparsable JSON responses for 401 and others better.
Python-rhsm should handle unparsable JSON responses for 401 and others better.
Status: CLOSED CURRENTRELEASE
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: python-rhsm (Show other bugs)
7.0
Unspecified Unspecified
unspecified Severity unspecified
: rc
: 7.0
Assigned To: Michael Stead
John Sefler
:
Depends On:
Blocks: rhsm-rhel70
  Show dependency treegraph
 
Reported: 2013-08-16 15:19 EDT by Alex Wood
Modified: 2014-06-17 20:26 EDT (History)
5 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2014-06-13 06:12:43 EDT
Type: Bug
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)

  None (edit)
Description Alex Wood 2013-08-16 15:19:46 EDT
Description of problem:
Python-rhsm has a method Restlib.validateResponse() that is called after a request is made to Candlepin/Katello/Whatever.  If the response is not a 200 or 204, python-rhsm attempts to look at the response body and determine what type of error to raise.  It's first action is to attempt to parse the response body as JSON.  In cases such as bug #995292 when the response body is empty or is not JSON, the validateResponse method raises a RemoteServerException if the response is a 404, 500, 502, 503, 504.  Otherwise, it raises a NetworkException.  The validateResponse() method should be modified so that it can handle empty or non-JSON response bodies better for errors such as 401 or 403.

How reproducible: Always

Steps to Reproduce:
1. On your candlepin server, stop candlepin.
2. On your candlepin server, run

openssl s_server -accept 8443 -key /etc/candlepin/certs/candlepin-ca.key -cert /etc/candlepin/certs/candlepin-ca.crt

3. On your subscription-manager machine, subscription-manager register --username=blah --password=blah --org=blah.

4. You should see the request print in the terminal window on the candlepin server.  This request will be for the candlepin version and it gets made every time you run a subscription-manager command.

5. Enter the following:

HTTP/1.1 401 Unauthorized
q 

6. Now a POST request will appear this time with a lot of JSON.  Enter the following.

HTTP/1.1 401 Unauthorized
q 

Actual results: Subscription-manager prints
Network error, unable to connect to server.
Please see /var/log/rhsm/rhsm.log for more information.

Expected results: A message indicating that the user's credentials were not accepted.

Additional info:
Hitting q on a line by itself when running s_server will end the current SSL connection but leave the server still running to accept new connections.

Do NOT add extra newlines when entering the response.  If the request ends without a newline (as it does for me when it makes the POST request) simply continue your response on the same line.

Additionally, you can test that the current functionality continues to work by providing the following response to the POST request:

HTTP/1.1 401 Unauthorized
 
{
  "displayMessage" : "Invalid credentials."
}
q
Comment 2 Michael Stead 2013-09-23 08:25:44 EDT
Fixed by:

https://github.com/candlepin/python-rhsm/pull/91

Available in python-rhsm-1.10.2-1
Comment 3 Bryan Kearney 2013-09-26 13:59:19 EDT
998033 python-rhsm-1.9.6-1
Comment 4 John Sefler 2013-09-27 14:51:39 EDT
Testing Version...
[root@jsefler-6 ~]# subscription-manager version
server type: This system is currently not registered.
subscription management server: 0.8.28-1
subscription-manager: 1.9.7-1.el6
python-rhsm: 1.9.6-1.el6


The test procedure provided in comment 0 is very interactive so I will paste it all here.  My results from testing with the procedure in comment 0 appear successful when I supply a response with JSON.  However I am unconvinced that the expected behavior is happening when the response has no JSON.

A 401 or 403 response with a JSON displayMessage from the server is successfully sent and displayed by the subscription-manager client as follows...

If I interactively send this back from the server...
HTTP/1.1 401 Unauthorized

{"displayMessage" : "Invalid credentials. Try Harder!!  Take a guess."}
q


Then I get this result on the client...
[root@jsefler-6 ~]# subscription-manager register --username=blah --password=blah --org=blah
Invalid credentials. Try Harder!!  Take a guess.


^^^ VERIFIED: This is what we want.

However, if I interactively send this back from the server (WITH NO JSON)...
HTTP/1.1 401 Unauthorized
q

Then I get this result on the client...
[root@jsefler-6 ~]# subscription-manager register --username=blah --password=blah --org=blah
Remote server error. Please check the connection details, or see /var/log/rhsm/rhsm.log for more information.

^^^ FailedQA:  I think we wanted to see...  "A message indicating that the user's credentials were not accepted.unauthorized."  I'm not really sure.

The rhsm.log shows...
2013-09-27 14:38:59,975 [DEBUG]  @connection.py:441 - Making request: POST /candlepin/consumers?owner=blah
2013-09-27 14:39:19,010 [DEBUG]  @connection.py:460 - Response status: 401
2013-09-27 14:39:19,013 [ERROR]  @managercli.py:150 - Error during registration: Server error attempting a POST to /candlepin/consumers?owner=blah returned status 401
Unauthorized: Invalid credentials for request.
2013-09-27 14:39:19,015 [ERROR]  @managercli.py:151 - Server error attempting a POST to /candlepin/consumers?owner=blah returned status 401
Unauthorized: Invalid credentials for request.
Traceback (most recent call last):
  File "/usr/share/rhsm/subscription_manager/managercli.py", line 1053, in _do_command
    installed_products=self.installed_mgr.format_for_server())
  File "/usr/lib64/python2.6/site-packages/rhsm/connection.py", line 722, in registerConsumer
    return self.conn.request_post(url, params)
  File "/usr/lib64/python2.6/site-packages/rhsm/connection.py", line 544, in request_post
    return self._request("POST", method, params)
  File "/usr/lib64/python2.6/site-packages/rhsm/connection.py", line 469, in _request
    self.validateResponse(result, request_type, handler)
  File "/usr/lib64/python2.6/site-packages/rhsm/connection.py", line 521, in validateResponse
    handler=handler)
UnauthorizedException: Server error attempting a POST to /candlepin/consumers?owner=blah returned status 401
Unauthorized: Invalid credentials for request.



Moving back to ASSIGNED / NEEDINFO on the case when no JSON is sent back from the server.
Comment 5 Michael Stead 2013-11-12 09:11:28 EST
Base exception was changed causing CLI/GUI to print a generic exception message in subscription-manager.


A pull request for this fix can be found here:

https://github.com/candlepin/subscription-manager/pull/818

I'll update the bug state when merged.
Comment 6 Carter Kozak 2013-11-13 13:45:54 EST
commit 3351fd648dd93adfbd4f7d98d7a4890400bc635b
Author: Michael Stead <mstead@redhat.com>
Date:   Fri Nov 8 12:06:47 2013 -0400

    998033: Handle Unauthorized/Forbidden exceptions in CLI/GUI
    
    - translate and print messages when caught in CLI
    - translate and show messages when caught in GUI
    
    This bug fix was required as we are now handling
    AuthenticationException directly in CLI/GUI which
    is the base exception for Authentication/Forbidden
    exceptions, which would result in a generic message
    instead of custom messages per exception type.
    
    Exception handling in CLI/GUI could use some work
    to remove the duplication, but that will be left
    for another commit.
Comment 8 John Sefler 2013-11-22 14:47:47 EST
Retesting Version...
[root@jsefler-7 ~]# subscription-manager version
server type: Red Hat Subscription Management
subscription management server: 0.8.33-1
subscription-manager: 1.10.7-1.el7
python-rhsm: 1.10.6-1.el7


Just as I did in comment 4, I'll re-test using the interactive procedure in comment 0 and paste the results here...


A 401 or 403 response with a JSON displayMessage from the server is successfully sent and displayed by the subscription-manager client as follows...

If I interactively send this back from the server...
HTTP/1.1 401 Unauthorized

{"displayMessage" : "Invalid credentials. Try Harder!!  Take a guess."}
q


Then I get this result on the client...
[root@jsefler-7 ~]# subscription-manager register --username=blah --password=blah --org=blah
Invalid credentials. Try Harder!!  Take a guess.


^^^ VERIFIED: This is what we want.


If I interactively send this back from the server (WITH NO JSON)...
HTTP/1.1 401 Unauthorized
q

Then I get this result on the client...
[root@jsefler-7 ~]# subscription-manager register --username=blah --password=blah --org=blah
Unauthorized: Invalid credentials for request.


^^^ VERIFIED: This *is* what we want and is better than what we saw in comment 4.

The rhsm.log shows...
2013-11-22 14:40:58,851 [DEBUG] subscription-manager @connection.py:467 - Response: status=401
2013-11-22 14:40:58,853 [ERROR] subscription-manager @managercli.py:155 - Error during registration: Server error attempting a POST to /candlepin/consumers?owner=blah returned status 401
Unauthorized: Invalid credentials for request.
2013-11-22 14:40:58,854 [ERROR] subscription-manager @managercli.py:156 - Server error attempting a POST to /candlepin/consumers?owner=blah returned status 401
Unauthorized: Invalid credentials for request.
Traceback (most recent call last):
  File "/usr/share/rhsm/subscription_manager/managercli.py", line 1059, in _do_command
    installed_products=self.installed_mgr.format_for_server())
  File "/usr/lib64/python2.7/site-packages/rhsm/connection.py", line 729, in registerConsumer
    return self.conn.request_post(url, params)
  File "/usr/lib64/python2.7/site-packages/rhsm/connection.py", line 551, in request_post
    return self._request("POST", method, params)
  File "/usr/lib64/python2.7/site-packages/rhsm/connection.py", line 476, in _request
    self.validateResponse(result, request_type, handler)
  File "/usr/lib64/python2.7/site-packages/rhsm/connection.py", line 528, in validateResponse
    handler=handler)
UnauthorizedException: Server error attempting a POST to /candlepin/consumers?owner=blah returned status 401
Unauthorized: Invalid credentials for request.
Comment 9 Ludek Smid 2014-06-13 06:12:43 EDT
This request was resolved in Red Hat Enterprise Linux 7.0.

Contact your manager or support representative in case you have further questions about the request.

Note You need to log in before you can comment on or make changes to this bug.