Search code examples
rubyrestrest-clientrtcrational-team-concert

Ruby RestClient to access Rational Team Concert (RTC) REST


I want to use the Ruby gem RestClient to access records from Rational Team Concert (RTC) over REST URLs. I have done this successfully with other servers. When I use the REST URL in Chrome directly, I can get a record. However, when I use my Ruby code, I get back some page that includes a line:

net.jazz.ajax._appPath = "/ccm0001001/auth/authrequired";

I've tried all sorts of ways to pass the credentials, but nothing seems to work. This is what I want to use:

response = RestClient::Request.new(
    :method => :get,
    :url => uri,
    :user => "username",
    :password => "password",
    :verify_ssl => OpenSSL::SSL::VERIFY_NONE
).execute

Anyone ever use Ruby (or Python?) to access RTC over REST URLs, or have any ideas what I'm doing wrong?

Thanks!


Solution

  • Not sure you are still stuck here, but for anyone else this might help.

    First Rational Team Concert(RTC) and the other Jazz based products default to Form based authentication by default, this can be changed by the Jazz Administrators to support the standard Basic authentication or more complex methods like certificate based authentication for common access cards and the like TN0013: Jazz Team Server Authentication Explained. It is easy to tell if you have Form or Basic authentication, when you try and login via the browser are you directed to a login servlet page or prompted for an operating system/browser dialog

    Form Auth redirects to login page like this: enter image description here

    Basic Auth prompts via browser: enter image description here

    I'll show some examples using Python and the Requests module to simplify the code, here is the leading boiler plate that proceeds the below snippets.

    import requests
    # quiet warnings for self-signed certificates
    requests.packages.urllib3.disable_warnings()
    
    base_url = "https://jazzserver.demo.com/ccm"
    auth_uri = "/authenticated/identity"
    
    jazz_user = "user"
    jazz_pass = "secretpassword"
    
    session = requests.Session()
    session.verify = False
    session.allow_redirects = True
    session.headers = {'accept':'application/xml'}
    

    If your administrator has activated Basic auth, then the example you provided would be sufficient as the authentication needed would already be in your session and when you requested a secured resource the credentials will be provided and your request will succeed.

    session.auth = (jazz_user, jazz_pass)
    
    # Request a protected resource, auth creds are stored in session
    response = session.get(base_url + auth_uri)
    

    Since your snippet above is not working, I would assume you are using Form authentication. In this case we need to do the standard form auth handshake of request a protected resource, follow redirect to form, post credentials to form with provided session id, verify we are logged in, and either follow redirect or retry protected resource.

    print "Request for authenticated resource"
    response = session.get(base_url + auth_uri)
    
    #print response.text
    print response.headers
    
    if 'x-com-ibm-team-repository-web-auth-msg' in response.headers and response.headers['x-com-ibm-team-repository-web-auth-msg'] == 'authrequired':
        print "Not currently authenticated"
    
        # Form response
        print "Sending login POST"
        login_response = session.post(base_url + '/j_security_check', data={ 'j_username': jazz_user, 'j_password': jazz_pass } )
        print login_response.headers
    
        if 'x-com-ibm-team-repository-web-auth-msg' in login_response.headers and login_response.headers['x-com-ibm-team-repository-web-auth-msg'] == 'authrequired':
            print "Failed to authenticate"
            print login_response.status_code
            print login_response.text
            raise Exception( "Failed to login: ", login_response.text )
    
        print "Getting authenticated resource again now that we should be logged in:"
        response = session.get( base_url + auth_uri )
    
    print response.headers
    print response.text
    

    I have not accessed a certificate based authentication server or have one set so I don't have any experience using the API against that yet.

    Posted a full example that should work for either Basic or Form auth as a GitHub gist

    Gist - rtc_request_example.py

    Should give you an output like this:

        (rtc_client)sgwilbur@gura:~/workspaces/rtc_helper$ ./test_ccm.py
        Request for authenticated resource
        {'x-com-ibm-team-repository-web-auth-msg': 'authrequired', 'content-length': '1985', 'set-cookie': 'JSESSIONID=CEF68A74B1A8005EB91A90BA42F3F86A; Path=/ccm/; Secure; HttpOnly, JazzFormAuth=Form; Path=/ccm; Secure', 'expires': 'Wed, 31 Dec 1969 18:00:00 CST', 'server': 'Apache-Coyote/1.1', 'cache-control': 'private', 'date': 'Thu, 15 Jan 2015 18:43:35 GMT', 'content-type': 'text/html;charset=UTF-8'}
        Not currently authenticated
        Sending login POST
        {'content-length': '55', 'set-cookie': 'JSESSIONID=1FE94776634391C83E47210113D1A4D4; Path=/ccm/; Secure; HttpOnly, JSESSIONIDSSO=D91E3A4E3376D567AF93DD031ED48E72; Path=/; Secure; HttpOnly, X-com-ibm-team-foundation-auth-loop-avoidance=false; Secure', 'expires': 'Wed, 31 Dec 1969 18:00:00 CST', 'server': 'Apache-Coyote/1.1', 'cache-control': 'private', 'date': 'Thu, 15 Jan 2015 18:43:36 GMT', 'content-type': 'text/json;charset=utf-8'}
        Getting authenticated resource again now that we should be logged in:
        {'content-length': '55', 'set-cookie': 'X-com-ibm-team-foundation-auth-loop-avoidance=false; Secure', 'expires': 'Wed, 31 Dec 1969 18:00:00 CST', 'server': 'Apache-Coyote/1.1', 'cache-control': 'private', 'date': 'Thu, 15 Jan 2015 18:43:36 GMT', 'content-type': 'text/json;charset=utf-8'}
        {
            "userId": "sgwilbur",
            "roles": [
                "JazzAdmins"]
        }
    

    -Sean