Maximo Open Forum

 View Only

 Python and Maximo REST API using APITOKEN to fetch meter data

  • Integrations
Alekhya Dadi's profile image
Alekhya Dadi posted 12-29-2020 08:32

I am trying to access Maximo location data using Python and Maximo REST API as detailed below on IBM site. I am using basic authentication to fetch the apikey.

Creating and using REST API keys in a secure application server environment

I do get the apikey just fine and while the query works fine in postman, Python code is throwing a bunch of HTML instead of what postman shows, a nice JSON response. What am I missing?

Here is the HTML that is returned. 

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=320, initial-scale=1.0" />
<meta name="format-detection" content="telephone=no" />

<link rel="apple-touch-icon" href="../images/maximo-icon.png?v2" />
<link rel="shortcut icon" href="../images/maximo-icon.ico?v2" />

                        <title>IBM&nbsp;Maximo</title>

<link href="css/login.css" rel="stylesheet" type="text/css" />


<link href="css/iot18/login.css" rel="stylesheet" type="text/css" />

</head>

<body onload="checkForRefresh()"
        >
        <div role="main">
                <table id="main_tbl" class="main_tbl" cellpadding="0" cellspacing="3"
                        role="presentation">
                        <tr role="banner">
                                <td>
                                         <img class="defaultbrandinglogo" src="images/tivoli_brandmark.png"
                                        alt="Tivoli" />
                                </td>
                                <td align="left"><img class="defaultibmlogo"
                                        src="images/ibm-logo-white.gif" alt="IBM" /></td>
                        </tr>
                        <tr>
                                <td class="dialog" colspan="2">

                                        <h1 class="prod_name"><span>IBM</span>&nbsp;<span>Maximo</span></h1>

                                        <table cellpadding="0" cellspacing="0" role="presentation">
                                                <tr>
                                                        <td colspan="5" align="left">

                                                                <h1 class="prod_name ext_prod_name" style="display: none"><span>IBM</span>&nbsp;<span>Maximo</span></h1>
                                                                <h1 class='sub_product'>Enterprise Asset Management</h1>

                                                        </td>
                                                </tr>
                                                <tr>

                                                        <td valign="top"><img class="prodIcon"
                                                                src="images/mx_icon_iot18.png" alt="" /></td>
                                                        <td class="input_pad">
                                                                <form id="loginform" name="loginform" method="post"
                                                                        action="../../j_security_check" onsubmit="loginSetup();" autocomplete="off"
                                                                        aria-label="Welcome">
                                                                        <input type="hidden" name="allowinsubframe"
                                                                                value="null" /> <input
                                                                                type="hidden" name="mobile" id="mobile" value="false" />
                                                                        <input type="hidden" name="login" id="loginjsp" value="jsp" />
                                                                        <input type="hidden" name="localStorage" id="localStorage"
                                                                                value="" /> <input type="hidden" name="loginstamp"
                                                                                id="loginstamp" value="1609247869959" />
                                                                        <label for="j_username" dir="ltr">User Name:</label><br />

                                                                        <input  style="width:195px"
                                                                                name="j_username" id="j_username"
                                                                                langcode="EN" type="text"
                                                                                value=""
                                                                                onchange="document.getElementById('forgot_j_username').value = this.value;if(document.getElementById('new_j_username'))document.getElementById('new_j_username').value = this.value;" />
                                                                        <br />
                                                                        <br /> <label for="j_password"
                                                                                dir="ltr">Password:</label><br /> <input
                                                                                style="width:195px"
                                                                                name="j_password" id="j_password"
                                                                                type="password" value="" autocomplete="off" /> <br />
                                                                        <br />

                                                                        <div style="text-align: left">
                                                                                <button class="tiv_btn" type="submit" id="loginbutton"
                                                                                        value="1">Sign In</button>
                                                                        </div>
                                                                </form>
                                                        </td>
                                                </tr>

                                        </table>
                                </td>
                        </tr>

                        <tr>
                                <td colspan="2" class="copyright" role="contentinfo"><img
                                        alt="IBM" src="images/ibm-logo-white.gif" style="display: none">
                                <p>© Copyright IBM Corp. 2007-2019. All rights reserved. See product license for details.</p></td>
                        </tr>
                </table>
        </div>

        <script language="JavaScript" type="text/javascript">
        var MAINDOC=document;
        function checkForRefresh()
        {
                document.cookie = "TJE= ; expires=-1; path=/";
                document.cookie = "TE3= ; expires=-1; path=/";
                if (MAINDOC.location != document.location)
                {
                        var hiddenFrame = parent.document.getElementById("commframe");
                        if (hiddenFrame != null)
                        {
                                var debugwindow = parent.document.getElementById("dockedHiddenFrame");
                                var hdrRow = parent.document.getElementById("debugHeaderRow");
                                hdrRow.style.display="none";
                                debugwindow.style.display="";
                                debugwindow.style.visibility="visible";
                                debugwindow.style.position="absolute";
                                debugwindow.style.top = -16 + "px";
                                debugwindow.style.left = -18 + "px";
                                debugwindow.style.opacity=1;
                                debugwindow.style.filter="alpha(opacity=100)";
                                debugwindow.style.width=parent.document.body.clientWidth +19 + "px";
                                debugwindow.style.height=parent.document.body.clientHeight + 16 + "px";
                                hiddenFrame.style.width=parent.document.body.clientWidth +19 + "px";
                                hiddenFrame.style.height=parent.document.body.clientHeight + 16 + "px";
                                debugwindow.style.zIndex=1001
                                hiddenFrame.style.display="inline";
                                parent.hideWait();
                        }
                }
                if(document.documentMode && (document.documentMode < 8))
                        alert("Either Compatibility View is turned on or you are using an unsupported browser version which can affect the performance of the product. Ensure that Compatibility View is turned off. If the issue continues, ensure that you are not using an unsupported browser version.");      

                var userField = document.getElementById("j_username");
                if (false || userField.value == "")
                {
                        userField.focus();
                        userField.select();
                }
                else
                {
                        var pWordField = document.getElementById("j_password");
                        if (pWordField.value == "")
                        {
                                pWordField.focus();
                                pWordField.select();
                        }
                        else
                        {
                                document.getElementById("loginbutton").focus();
                        }
                }
                window.setTimeout("document.location='exit.jsp?logintimeout=1'", 7190000);

                if (navigator.userAgent.toLowerCase().indexOf("iphone") > -1)
                {
                        setTimeout(hideURLbar, 0);
                }
        }

        function loginSetup()
        {
                showWait();
        }
        document.getElementById("localStorage").value = ('localStorage' in window && window['localStorage'] !== null);
        function selectLanguage()
        {
                var langform = document.getElementById("langform");
                var username = document.getElementById("j_username");
                        if (username && username.value) {
                                langform.languser.value = username.value;
                        }
                        langform.submit();
                }

                function showWait() {
                        document.body.style.cursor = "wait";
                        document.body.onkeydown = noKeys;

                        var lb = document.getElementById("loginbutton");
                        if (lb) {
                                lb.disabled = true;
                                lb.setAttribute("aria-disabled", "true");
                        }

                        var main_tbl = document.getElementById("main_tbl");
                        if (main_tbl) {
                                main_tbl.style.display = "none";
                                main_tbl.setAttribute("aria-hidden", "true");
                        }
                }

                function noKeys(event) {
                        event = event || window.event;
                        if (event.stopPropagation) {
                                event.stopPropagation();
                                event.preventDefault();
                        } else {
                                event.cancelBubble = true;
                                event.returnValue = false;
                        }
                        return false;
                }

                function hideURLbar() {
                        window.scrollTo(0, 1);
                }
        </script>
</body>

</html>

Here is the Python code - 

import requests
import json

url = "https://maximositeip/maxrest/oslc/apitoken/create"

payload = "{\r\n     \"expiration\":-1\r\n}"
headers = {
    'content-type': "application/json",
    'authorization': "Basic bHF4YBVpaW65bWW4YWRtaW8=",
    'cache-control': "no-cache"
    }

response = requests.request("POST", url, data=payload, headers=headers, verify=False)

#print(response.text)
resp_dict = json.loads(response.text)
print(resp_dict['apikey'])
apikey = resp_dict['apikey']

url = "https://maximositeip/maximo/oslc/os/mxapiasset"

headers = {
    'apikey': apikey,
    'x-public-uri' : "http://maximositeip/maximo/api",
    'content-type' : "application/json"
    }

response = requests.request("GET", url, headers=headers, verify=False)

print(response.text)

I get the apikey as the output and the HTML referenced above. Please guide me. Using Maximo 7.6.1.1. Thanks!

Steven Shull's profile image
Steven Shull
Since you're using basic auth, you're using LDAP (or a combination of LDAP & SAML). Regardless, that means the /maximo/oslc route is protected by WebSphere which requires authentication at the WebSphere layer before Maximo can even check the API key. Since you're on 7.6.1.1, you should replace any reference to /maximo/oslc with /maximo/api

The /maximo/api route is identical to the /maximo/oslc but is not protected by WebSphere so that Maximo can enforce the security and this is where the API key will be used. This didn't exist until 7.6.1.1 but you mentioned you're on 7.6.1.1 so you should have it. You provided it as a header, so you were pretty close, but still had the URL referenced as /maximo/oslc which is why you were being redirected to the login page.
Alekhya Dadi's profile image
Alekhya Dadi
@Steven Shull Thanks for that OSLC to API change. Completely missed that one. The explanation really helped understand the underlying technicalities.

​After making the change, I now see this instead -

url = "https://maximoeaminttest:8443/maximo/api/os/mxapiasset"

Is it possible IT did not set this integration up for API access properly?


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>404 Not Found</title>
</head>
<body>
The server has encountered an unknown error. Reload the application and try again. If the problem persists, contact your system administrator.<br/><br/>Error code: 404
</body>
</html>
Steven Shull's profile image
Steven Shull
@Alekhya Dadi Are you sure you're on 7.6.1.1 of Maximo (and not 7.6.1.1 of Control desk for example)? This was added in Maximo 7.6.1.1 and it's enabled by default. If they knew about it they could have removed it from the web.xml but being a newer feature that most people wouldn't be aware about I would be surprised if they removed it. Assuming you're on a version between 7.6.0.9 and 7.6.1.0, you can follow the steps in the IBM guide to add this to the web.xml in those versions. 

Overview (ibm.com)

I initially thought that maybe they had changed the context from being /maximo to some other context (such as /maxtest), but because you got the Maximo login page before that would eliminate that.
Alekhya Dadi's profile image
Alekhya Dadi
@Steven Shull

I did a GET on oslc/systeminfo -

Should I be looking for a different component's version info?

"spi:versionKey": "IBM Maximo Asset Management 7.6.1.1 Build 20190514-1348 DB Build V7611-01"
"spi:versionKey": "IBM Tpae Integration Framework 7.6.1.1 Build 20190419-2330 DB Build V7611-01"

​I do not have access to web.xml but I will work with IT if needed but that takes a long time for anything to get changed even in lower environments.
Steven Shull's profile image
Steven Shull
Yeah unfortunately it looks like you'll need to reach out to them. That is the appropriate version where it was added so it should be there from a Maximo perspective.

The reason why I asked to verify is Control Desk has a 7.6.1.1 version that is based on the framework of Maximo 7.6.1.0 and some people reference Control Desk & Maximo interchangeably since Maximo is more well known.
Alekhya Dadi's profile image
Alekhya Dadi
@Steven Shull - IT finally made the change in the config. Now I get this error - Is SPNEGO authentication needed to use APITOKEN? 

This call is throwing the error. I am now able to create the token though.
"https://maximositeip/maximo/oslc/os/mxapiasset"​

Error

<html><head><title>SPNEGO authentication is not supported.</title></head><body>SPNEGO authentication is not supported on this client.</body></html>
Steven Shull's profile image
Steven Shull
@Alekhya Dadi All requests with API keys should go to /maximo/api (creating the key and accessing the data). This is an unprotected route so the WebSphere settings (like SPNEGO, LDAP, SAML, etc.) are bypassed so the application can manage access with the API keys. Unless you want to use the OSLC API (IE spi:attribute), you'll also always want to provide the lean=1 query parameter. ​
Biplab Choudhury's profile image
Biplab Choudhury
I see you are using https. 
first all of please debug your request in Maximo as that would give you better idea of what is going wrong.

Anyways, one issue I faced in the rest api calls is the tls version not set by Maximo. Try to set TLS version in your request. Use the tls version of Maximo app server.